Эталонная модель Open Distributed Processing - написанный Международной организации по стандартизации - определяет следующие понятия:
Entity: Любые конкретные или абстрактный предмет интереса.
Объект: Модель объекта. Объект характеризуется своим поведением и, как правило, его состоянием.
Поведение (объекта): совокупность действий с набором ограничений, когда они могут возникнуть.
Интерфейс: абстракция поведения объекта, состоящего из подмножества взаимодействий этого объекта вместе с набором ограничений, когда они могут возникнуть.
Инкапсуляция: свойство, что информация, содержащаяся в объекте, доступна только через взаимодействия на интерфейсах, поддерживаемых объектом.
Эти, вы оцените, довольно широкие. Давайте посмотрим, однако, можно ли считать функциональность внутри функции логически считающейся для инкапсуляции в этих терминах.
Во-первых, функция явно является моделью «Интересности», поскольку она представляет собой алгоритм, который вы (предположительно) выполняете, и этот алгоритм относится к какой-либо проблеме, которую вы пытаетесь решить (и, следовательно, это его модель).
Имеет ли функция поведение? Это, безусловно, делает: он содержит коллекцию действий (которые могут быть любым количеством исполняемых инструкций), которые выполняются под ограничением, что функция должна вызываться из где-то, прежде чем она сможет выполнить. Функция не может быть вызвана спонтанно в любое время без причинного фактора. Похоже на легализацию? Еще бы. Но давайте пахаем, тем не менее.
Есть ли у функции интерфейс? Это, безусловно, имеет: оно имеет имя и набор формальных параметров, которые, в свою очередь, сопоставляются с исполняемыми операциями, содержащимися в функции, в том, что, как только функция вызывается, в имени и списке параметров понимается уникальная идентификация коллекции исполняемых файлов операторы, которые будут выполняться без указания вызывающей стороны этих фактических операторов.
Имеет ли функция свойство, что информация, содержащаяся в этой функции, доступна только через взаимодействия на интерфейсах, поддерживаемых объектом? Хм, ну, может.
Поскольку какая-либо информация доступна через ее интерфейс, некоторая информация должна быть скрыта и недоступна внутри функции. (Свойство таких информационных экспонатов называется скрытием информации, которое Парнас определил, утверждая, что модули должны быть разработаны, чтобы скрыть как сложные решения, так и решения, которые могут измениться.) Итак, какая информация скрыта внутри функции?
Чтобы увидеть это, мы должны сначала рассмотреть масштаб. Легко утверждать, что, например, классы Java могут быть инкапсулированы внутри пакета: некоторые из классов будут общедоступными (и, следовательно, будут интерфейсом пакета), а некоторые будут закрытыми для пакета (и, следовательно, информацией, скрытыми внутри пакета) , В теории инкапсуляции классы образуют узлы и пакеты образуют инкапсулированные области, причем целое образует инкапсулированный граф; график классов и пакетов называется третьим графиком.
Также легко утверждать, что сами функции (или методы) инкапсулируются внутри классов. Опять же, некоторые функции будут общедоступными (и, следовательно, будут частью интерфейса класса), а некоторые будут частными (и, следовательно, скрытыми от информации в классе).График функций и классов называется вторым графом.
Теперь мы приходим к функциям. Если сами функции должны быть самим средством инкапсуляции, они должны содержать некоторую информацию публично для других функций и некоторую информацию, скрытую внутри функции. Что может быть эта информация?
Один кандидат дается нам МакКейбом. В своей важной статье о циклической сложности Томас МакКейб описывает исходный код, где «каждый узел в графе соответствует блоку кода в программе, где поток последователен, а дуги соответствуют ветвям, принятым в программе».
Возьмем блок последовательного исполнения МакКабиан как единицу информации, которая может быть инкапсулирована внутри функции. Поскольку первый блок внутри функции всегда является первым и единственным гарантированным блоком, который может быть выполнен, мы можем считать, что первый блок является общедоступным, поскольку он может быть вызван другими функциями. Тем не менее, все остальные блоки внутри функции не могут быть вызваны другими функциями (кроме языков, которые позволяют переходить в функции mid-flow), и поэтому эти блоки могут считаться скрытыми внутри функции.
Принимая эти (возможно, слегка слабые) определения, тогда мы можем сказать «да»: включение функциональных возможностей внутри функции составляет инкапсуляцию. Инкапсуляция блоков внутри функций - это первый график.
Существует, однако, оговорка. Вы рассмотрели бы пакет, каждый из которых был бы общедоступным для инкапсуляции? Согласно вышеприведенным определениям, он проходит тест, так как вы можете сказать, что интерфейс к пакету (т. Е. Все публичные классы) действительно предлагает подмножество поведения пакета для других пакетов. Но подмножество в этом случае - это поведение всего пакета, так как ни один из классов не скрывает информацию. Таким образом, несмотря на то, что мы строго соблюдаем приведенные выше определения, мы чувствуем, что он не удовлетворяет духу определений, так как что-то должно быть скрыто для истинной инкапсуляции.
То же самое верно для экзамена, который вы даете. Разумеется, мы можем считать n = n + 1 единым блоком МакКабиана, так как он (и оператор return) представляет собой единый последовательный поток исполнений. Но функция, в которую вы помещаете это, содержит только один блок, и этот блок является единственным публичным блоком функции, поэтому в вашей предлагаемой функции нет скрытых в информации блоков. Поэтому он может удовлетворить определение инкапсуляции, но я бы сказал, что он не удовлетворяет духу.
Все это, конечно же, является академическим, если вы не можете доказать свою выгоду такой инкапсуляции.
Есть две силы, которые мотивируют инкапсуляцию: семантическую и логическую.
Семантическая инкапсуляция просто означает инкапсуляцию, основанную на значении узлов (для использования общего термина). Поэтому, если я скажу вам, что у меня есть два пакета, один из которых называется «животное», а один называется «минералом», а затем дает вам три класса «Собака», «Кошка и козел» и спрашивать, в каких пакетах эти классы должны быть инкапсулированы, нет никакой другой информации, вы были бы совершенно правы утверждать, что семантика системы предполагает, что три класса будут инкапсулированы в пакет «животное», а не в «минерал».
Другая мотивация для инкапсуляции, однако, является логикой.
Конфигурация системы - это точная и исчерпывающая идентификация каждого узла системы и инкапсулированной области, в которой она находится; конкретная конфигурация системы Java - на третьем графике - для идентификации всех классов системы и указания пакета, в котором находится каждый класс.
Чтобы логически инкапсулировать систему, нужно идентифицировать математическое свойство системы, которое зависит от его конфигурации, а затем настроить эту систему, чтобы свойство было математически минимизировано.
Теория инкапсуляции предполагает, что все инкапсулированные графы выражают максимальное потенциальное число ребер (MPE). Например, в Java-системах классов и пакетов MPE представляет собой максимальное потенциальное число зависимостей исходного кода, которое может существовать между всеми классами этой системы. Два класса в одном пакете не могут быть скрыты друг от друга, и поэтому оба могут потенциально создавать взаимозависимости друг с другом. Однако два класса с частными пакетами в отдельных пакетах могут не создавать зависимости друг от друга.
Теория инкапсуляции сообщает нам, сколько пакетов мы должны иметь для заданного количества классов, чтобы минимизировать MPE. Это может быть полезно, потому что слабая форма Принципа Бремена утверждает, что максимальная потенциальная нагрузка на преобразование совокупности объектов зависит от максимального потенциального числа преобразованных объектов - другими словами, чем больше потенциальных зависимостей исходного кода у вас есть между ваши классы, тем больше потенциальная стоимость любого конкретного обновления. Минимизация MPE позволяет минимизировать максимальную потенциальную стоимость обновлений.
Учитывая, что n классов и требование p общедоступных классов на пакет, теория инкапсуляции показывает, что количество пакетов, r, мы должны минимизировать MPE, задается уравнением: r = sqrt (n/p).
Это также относится к числу функций, которые вы должны иметь, учитывая общее количество n блоков McCabian в вашей системе. Функции всегда имеют только один публичный блок, как мы упоминали выше, и поэтому уравнение для числа функций r, которое должно иметь в вашей системе, упрощается: r = sqrt (n).
Понятно, что некоторые люди рассматривали общее количество блоков в своей системе при осуществлении инкапсуляции, но это легко сделать на уровне класса/пакета. И, кроме того, минимизация MPE почти полностью интуитивно понятна: это делается путем сведения к минимуму количества публичных классов и попыток равномерного распределения классов по пакетам (или, по крайней мере, избегать большинства пакетов с, скажем, 30 классами, и одного монстра pacakge с 500 классами, в этом случае внутренний MPE последнего может легко перегружать MPE всех остальных).
Таким образом, инкапсуляция предполагает достижение баланса между семантическим и логическим.
Все большое удовольствие.
Если функция была вызвана «AddX», где X - это значение, которое в настоящее время имеет значение 1, но это может измениться, тогда будет скрыта информация. Добавленное конкретное значение будет скрыто в определении функции. –
Кроме того, функции определенно разделяют ответственность. Каждая функция несет ответственность за то, чего не выполняют другие функции. Да, данный набор функций может быть плохо разработан, поэтому они перекрываются, но тогда то же самое относится к плохо разработанному набору классов. –
@Serx Функция addOne выражает «что» это делает и скрывает «как» она это делает. Таким образом, это будет квалифицироваться как абстракция + скрытие информации. Почему вы так сосредоточены на объектах? И, как утверждает Эрвиккер, функции могут разделить ответственность, но я нахожу это довольно расплывчатым критерием для инкапсуляции. – eljenso