запахи кода глобальные переменные
Поскольку «Расширения не могут содержать сохраненные свойства», я видел, как люди обходили это, используя геттер / сеттер с objc_getAssociatedObject / objc_setAssociatedObject
Я считаю, что обсуждаемые там решения очень «неумелые», но все же предпочитаю держать переменные ближе к тому месту, где они используются.
Вот почему я недавно начал делать следующее, когда хочу использовать «свойство» в расширении.
Поскольку я не нашел этого решения в другом месте, мне интересно, это запах кода или какие недостатки с ним связаны.
Подумайте об этом: что произойдет, если у вас есть два экземпляра этого класса и установить значение для каждого из них?
В чем причина того, что мы не можем легко добавлять свойства к расширению?
Потому что добавление свойств изменяет размер объекта. ViewControllers, созданные в другом модуле, не смогут узнать, сколько памяти выделить. Добавление этой функции потребовало бы создания чего-то вроде objc_getAssociatedObject в Swift, что может быть возможно когда-нибудь для классов (хотя я сомневаюсь, что когда-либо для структур).
Сравнить stackoverflow.com/a/45495616/1187415: «Потому что добавление свойства экземпляра изменит размер экземпляров этого типа»
Это приводит к утечке памяти (поскольку нет автоматического способа очистки неиспользуемых значений), но затраты обычно невелики (или вам нужно добавить механизм «сборки мусора», что не так уж сложно).
Я не тестировал это всесторонне, но это пример того, как вы можете создать версию с автоматическим сбором мусора, чтобы очистить память, если у вас было много объектов, которые приходят и уходят. Он собирает мусор каждый раз, когда вы его изменяете, но вы можете сделать это другими способами, в зависимости от необходимости:
При этом использование почти идентично:
Является ли запах кода для использования частных глобальных переменных в качестве свойств расширения?
Поскольку “Расширения могут не содержать хранимых свойств”, я видел, как люди objc_getAssociatedObject это, используя getter/setter с objc_getAssociatedObject / objc_setAssociatedObject
Я нахожу, что обсуждаемые там решения очень “непривлекательны”, но все равно любят держать переменные близко к тому, где они используются.
Вот почему я недавно начал делать следующее, когда хочу использовать свойство в расширении.
Поскольку я не нашел это решение в другом месте, я задаюсь вопросом, является ли это запахом кода или какие недостатки приходят с ним.
То, что другие расширения в этом исходном файле могут получить доступ к lastValue – это то, с чем я могу жить, потому что расширение есть в нем собственный исходный файл.
Это утечка некоторой памяти (поскольку нет автоматического способа удаления неиспользуемых значений), но стоимость обычно мала (или вам нужно добавить механизм “сбор мусора”, который не слишком сложный).
Я не тестировал это широко, но это пример того, как вы можете создать сборку мусора, чтобы очистить память, если у вас было много объектов, которые приходят и уходят. Это мусор собирает каждый раз, когда вы его модифицируете, но вы можете сделать это по-другому, в зависимости от необходимости:
При этом использование почти идентично:
Глобальные переменные лучше избегать. Я бы рекомендовал сделать var var переменной частного экземпляра, а не глобальной.
Разумно иметь частные переменные, которые добавляются к объекту для поддержки “родных” расширений. (Расширение, которое определено в том же исходном файле, что и исходный объект, на самом деле является просто способом группировки кода, поскольку он “запекается” в базовом объекте.
Использование objc_setAssociatedObject для добавления хранения в NSObject подклассов является вариантом для расширений, которые расширяют другие классы. Вы должны знать, что существует небольшая временная штрафная ставка, но если вы не ссылаетесь на связанный объект повторно в цикле, это вряд ли будет проблемой. Он также требует, чтобы объектом был объект Objective-C, который также имеет небольшое временное ограничение.
Использование objc_setAssociatedObject также делает ваш код Swift только для Apple. если вы строите код, который вы собираетесь использовать в Linux, это не вариант.
Я нахожу обсуждаемые там решения очень «непростыми», но все же предпочитаю держать переменные ближе к тому месту, где они используются.
Вот почему я недавно начал делать следующее, когда хочу использовать «свойство» в расширении.
Поскольку я не нашел этого решения в другом месте, мне интересно, это запах кода или какие недостатки с ним связаны.
2 ответа
Это приводит к утечке некоторой памяти (поскольку нет автоматического способа очистки неиспользуемых значений), но затраты обычно невелики (или вам нужно добавить механизм «сборки мусора», что не так уж сложно).
Я не тестировал это всесторонне, но это пример того, как вы можете создать версию с автоматическим сбором мусора для очистки памяти, если у вас было много объектов, которые приходят и уходят. Он собирает мусор каждый раз, когда вы его изменяете, но вы можете сделать это другими способами в зависимости от необходимости:
При этом использование почти идентично:
Лучше избегать глобальных переменных. Я бы рекомендовал сделать ваш var переменной частного экземпляра, а не глобальной.
Разумно иметь частные переменные, которые добавляются к объекту для поддержки «собственных» расширений. (Расширение, которое определено в том же исходном файле, что и исходный объект, на самом деле является просто способом группировки кода, поскольку оно «встроено» в базовый объект.
Использование objc_setAssociatedObject для добавления хранилища к подклассам NSObject является вариантом для расширений, расширяющих другие классы. Вы должны знать, что есть небольшая потеря времени, но, если вы не ссылаетесь на связанный объект повторно в цикле, это вряд ли будет проблемой. Также требуется, чтобы объект был объектом Objective-C, что также имеет небольшой временной штраф.
Использование objc_setAssociatedObject также делает ваш код Swift доступным только для Apple. если вы создаете код, который собираетесь использовать в Linux, это не вариант.
Запахи кода
— Что? Как может пахнуть код?
— Да, пахнуть определенно не может. а вот пованивать — запросто.
Раздувальщики
Раздувальщики представляют код, методы и классы, которые раздулись до таких больших размеров, что с ними стало невозможно эффективно работать. Все эти запахи зачастую не появляются сразу, а нарастают в процессе эволюции программы (особенно когда никто не пытается бороться с ними).
Нарушители объектного дизайна
Все эти запахи являют собой неполное или неправильное использование возможностей объектно-ориентированного программирования.
Утяжелители изменений
Эти запахи приводят к тому, что при необходимости что-то поменять в одном месте программы, вам приходится вносить множество изменений в других местах. Это серьезно осложняет и удорожает развитие программы.
Замусориватели
Замусориватели являют собой что-то бесполезное и лишнее, от чего можно было бы избавиться, сделав код чище, эффективней и проще для понимания.
Опутыватели связями
Все запахи из этой группы приводят к избыточной связанности между классами, либо показывают, что бывает, если тесная связанность заменяется постоянным делегированием.
Является ли запах кода для использования частных глобальных переменных в качестве свойств расширения?
Поскольку «Расширения могут не содержать хранимых свойств», я видел, как люди objc_getAssociatedObject это, используя getter/setter с objc_getAssociatedObject / objc_setAssociatedObject
Я нахожу, что обсуждаемые там решения очень «непривлекательны», но все равно любят держать переменные близко к тому, где они используются.
Вот почему я недавно начал делать следующее, когда хочу использовать свойство в расширении.
Поскольку я не нашел это решение в другом месте, я задаюсь вопросом, является ли это запахом кода или какие недостатки приходят с ним.
Это утечка некоторой памяти (поскольку нет автоматического способа удаления неиспользуемых значений), но стоимость обычно мала (или вам нужно добавить механизм «сбор мусора», который не слишком сложный).
Я не тестировал это широко, но это пример того, как вы можете создать сборку мусора, чтобы очистить память, если у вас было много объектов, которые приходят и уходят. Это мусор собирает каждый раз, когда вы его модифицируете, но вы можете сделать это по-другому, в зависимости от необходимости:
При этом использование почти идентично:
Глобальные переменные лучше избегать. Я бы рекомендовал сделать var var переменной частного экземпляра, а не глобальной.
Разумно иметь частные переменные, которые добавляются к объекту для поддержки «родных» расширений. (Расширение, которое определено в том же исходном файле, что и исходный объект, на самом деле является просто способом группировки кода, поскольку он «запекается» в базовом объекте.
Использование objc_setAssociatedObject для добавления хранения в NSObject подклассов является вариантом для расширений, которые расширяют другие классы. Вы должны знать, что существует небольшая временная штрафная ставка, но если вы не ссылаетесь на связанный объект повторно в цикле, это вряд ли будет проблемой. Он также требует, чтобы объектом был объект Objective-C, который также имеет небольшое временное ограничение.
Использование objc_setAssociatedObject также делает ваш код Swift только для Apple. если вы строите код, который вы собираетесь использовать в Linux, это не вариант.