В Cocoa есть несколько примеров решения подобной задачи:
1. NSTableView создает столько строк, сколько помещается на экране, и переиспользует их при прокрутке. Данные для каждой видимой строки выдает объект-источник данных.
2. Для некоторых объектов тяжелого класса NSView используются легковесные объекты класса NSCell, которые отвечают лишь за отрисовку содержимого. Например, матрица 10x10 является объектом NSView, а отрисовкой занимаются 100 клеток NSCell. Во время какого-нибудь события ОС не должна сообщать о нем каждой ячейки, а только одной матрице. А она уже сама разберется что с ним делать.
3. Если в окошке присутствует 100 текстовых полей, было бы неэффективно создавать объект-редактор для каждого поля (тормоза при создании + использование памяти). Вместо этого, окно содержит единственный редактор текста, а каждое поле при получении фокуса спрашивает его, размещает как следует и принимает данные.
Кокоа, как правило, не пытается сделать какие-то скрытые фичи типа переиспользуемых объектов, а просто предлагает интерфейс для оптимизации работы с большим количеством объектов.
Т.е. забота перекладывается на программиста, но зато программист работает с понятным фреймворком и всегда знает как организовать свой код.
Универсально оптимизировать работу с большим количеством однотипных объектов можно с помощью аллокатора, который размещает объекты одного класса в гомогенный массив. Но это будет лишь оптимизация доступа к данным самого объекта в цикле, а все остальные объекты, на которые он ссылается, будут размещены где попало.
Ну, еще malloc будет реже вызываться если переиспользовать освобожденные объекты. Но если переиспользовать объекты, то их порядок в массиве будет случайным, что существенно снизит и так низкую эффективность.
В итоге, нужно размещать данные так как нужно, в каждом конкретном случае. Не полагаясь на магию компилятора.
Кстати говоря, не только в «GUI» приложениях случаются события. Возьмите любой веб-сервер или CLI (командную строку).
Если же в каком-то месте создается много объектов которые имеет смысл удалить, не дожидаясь окончания обработки текущего события (чтобы не занимать слишком много памяти), то можно создать локальный пул. При этом в данном конкретном месте автору кода будет совершенно очевидно где этот пул должен быть очищен и какие объекты нужно retain-ить перед очисткой.
Управление памятью ручное, но совершенно понятное: кто сделал alloc, copy или retain, тот и делает release. Ни разу не приходилось «извращаться» или что-то проталкивать. Например, properties сами делают retain/release при записи и retain+autorelease при чтении. Так что единственное, что следует делать вручную — присвоить nil всем свойствам в методе dealloc (что автоматизируется благодаря информации о свойствах и их типах доступной в рантайме).
Когда я пишу сайтики и скрипты на руби, производительности интерпретатора и его тупого сборщика мусора мне вполне хватает. В крайнем случае, куплю железа по-мощнее. На десктопе или того хуже — на карманном компьютере я не могу докупить железа. И там как раз всевозможные интерпретаторы и сборщики мусора очень сильно тормозят. Это хорошо заметно при сравнении андроида и айфона.
Иными словами, интересно не то, что правильнее — наличие GC или отсутствие, а среда в которой делается работа. Например, андроидная джава ничем не удобнее и не гибче objective-c. И там и там — статические типы и многословные конструкции. И думать про дизайн и производительность нужно гораздо больше времени, нежели писать [something release].
Руби, с другой стороны, не только сборщик мусора предоставляет, но и лаконичный и гибкий язык. Так что сайтики делать на нем гораздо удобнее, чем на обжси или джаве. Но в айфоне он будет слишком медленно работать.
В objective-c эта проблема решена довольно остроумно. Во-первых, для всех объектов типа NSObject используется подсчет ссылок. Во-вторых, есть autorelease pulls, в которые как раз и попадают возвращаемые объекты. Если возвращенную строку никто к себе не забрал, то она будет удалена при очистке пула. Пулы живут только на одном потоке и могут быть вложенными. В каждом приложении есть основной поток, в котором есть основной RunLoop, который имеет свой пул, очищаемый после обработки каждого события.
Работает так:
NSObject* autoreleasedObject()
{
// autorelease поместит объект в ближайший пул в текущем потоке
return [[[NSObject alloc] init] autorelease];
}
Нет, такое гит не поддерживает: вы клонируете весь репозиторий и делаете с ним, что хотите. Поддерживается лишь хранение юникс-атрибутов rwx, но это не ограничивает доступ.
Если хотите разграничить доступ — разбивайте проект на разные репозитории, кладите на защищенный сервер и ограничивайте доступ к каждому репозиторию (например, с помощью gitosis, а можно и просто юникс-средствами ограничить доступ к определенным директориям на сервере).
Это круто когда у вас любовь с апачем и странными хостингами. Если что-то сложное нужно вертеть, то лучше кластера собственных демонов под нгинксом ничего нет. Апач посередине — это дополнительный расход памяти и cpu. Но если сложности не нужны, то mod_rack — отличная штука (мерб и прочие rack-совместимые приложения оно тоже вертеть умеет, поэтому переименовали в mod_rack)
«не вызывая подозрений у работодателя, который подчас может нервно среагировать на вывешивание резюме на популярных работных сайтах»
Какое-то феодальное восприятие. Сотрудник, ценящий свою работу и себя, может всегда быть в поиске работы. Ровно как работодатель — всегда в поиске новых, лучших, сотрудников. Нервничать нужно когда производительность падает или настроение ухудшается.
Тут нет спора. Товарищ мне ответил на «т.е. недопрограммеры так и норовят загрузить util.reflect и залезть в private-поля?» тем, что да, норовят. Мне становится интересно, где же водятся такие страшные программеры. Соображения инкапсуляции тут ни при чем. И спора тоже нет. Раз есть суровые челябинские программеры, нужно защищаться, конечно. Просто это как-то сюрреалистично смотрится.
Я имею в виду, что предлагается писать System.setSecurityManager(new SecurityManager()) чтобы не дать Васе завести свою переменную через java.util.reflect. Возникает вопрос: почему бы Васю не уволить, или научить, что делать a.getClass().getDeclaredField(«x») не следует. Или, что лучше, поинтересоваться, по какой такой причине ему нужно залезть в класс именно так. Мож, он баг какой так хитро патчит.
К инкапсуляции и ооп мое любопытство не имеет прямого отношения.
Уважаемое хабрачмо, хватит тут минусовать коллегу! Если идет дискуссия, есть два мнения. А минусовать нужно за спам и глупости. Опускание оппонента в _дискуссии_ не идет на пользу никому.
Не только для отладки. А вообще для метапрограммирования, для генерации кода. Посмотрите на API ActiveRecord, DataMapper — отличные примеры грамотной (в меру :-) генерации кода.
1. NSTableView создает столько строк, сколько помещается на экране, и переиспользует их при прокрутке. Данные для каждой видимой строки выдает объект-источник данных.
2. Для некоторых объектов тяжелого класса NSView используются легковесные объекты класса NSCell, которые отвечают лишь за отрисовку содержимого. Например, матрица 10x10 является объектом NSView, а отрисовкой занимаются 100 клеток NSCell. Во время какого-нибудь события ОС не должна сообщать о нем каждой ячейки, а только одной матрице. А она уже сама разберется что с ним делать.
3. Если в окошке присутствует 100 текстовых полей, было бы неэффективно создавать объект-редактор для каждого поля (тормоза при создании + использование памяти). Вместо этого, окно содержит единственный редактор текста, а каждое поле при получении фокуса спрашивает его, размещает как следует и принимает данные.
Кокоа, как правило, не пытается сделать какие-то скрытые фичи типа переиспользуемых объектов, а просто предлагает интерфейс для оптимизации работы с большим количеством объектов.
Т.е. забота перекладывается на программиста, но зато программист работает с понятным фреймворком и всегда знает как организовать свой код.
Универсально оптимизировать работу с большим количеством однотипных объектов можно с помощью аллокатора, который размещает объекты одного класса в гомогенный массив. Но это будет лишь оптимизация доступа к данным самого объекта в цикле, а все остальные объекты, на которые он ссылается, будут размещены где попало.
Ну, еще malloc будет реже вызываться если переиспользовать освобожденные объекты. Но если переиспользовать объекты, то их порядок в массиве будет случайным, что существенно снизит и так низкую эффективность.
В итоге, нужно размещать данные так как нужно, в каждом конкретном случае. Не полагаясь на магию компилятора.
Если же в каком-то месте создается много объектов которые имеет смысл удалить, не дожидаясь окончания обработки текущего события (чтобы не занимать слишком много памяти), то можно создать локальный пул. При этом в данном конкретном месте автору кода будет совершенно очевидно где этот пул должен быть очищен и какие объекты нужно retain-ить перед очисткой.
Когда я пишу сайтики и скрипты на руби, производительности интерпретатора и его тупого сборщика мусора мне вполне хватает. В крайнем случае, куплю железа по-мощнее. На десктопе или того хуже — на карманном компьютере я не могу докупить железа. И там как раз всевозможные интерпретаторы и сборщики мусора очень сильно тормозят. Это хорошо заметно при сравнении андроида и айфона.
Иными словами, интересно не то, что правильнее — наличие GC или отсутствие, а среда в которой делается работа. Например, андроидная джава ничем не удобнее и не гибче objective-c. И там и там — статические типы и многословные конструкции. И думать про дизайн и производительность нужно гораздо больше времени, нежели писать [something release].
Руби, с другой стороны, не только сборщик мусора предоставляет, но и лаконичный и гибкий язык. Так что сайтики делать на нем гораздо удобнее, чем на обжси или джаве. Но в айфоне он будет слишком медленно работать.
В objective-c эта проблема решена довольно остроумно. Во-первых, для всех объектов типа NSObject используется подсчет ссылок. Во-вторых, есть autorelease pulls, в которые как раз и попадают возвращаемые объекты. Если возвращенную строку никто к себе не забрал, то она будет удалена при очистке пула. Пулы живут только на одном потоке и могут быть вложенными. В каждом приложении есть основной поток, в котором есть основной RunLoop, который имеет свой пул, очищаемый после обработки каждого события.
Работает так:
NSObject* autoreleasedObject()
{
// autorelease поместит объект в ближайший пул в текущем потоке
return [[[NSObject alloc] init] autorelease];
}
Если хотите разграничить доступ — разбивайте проект на разные репозитории, кладите на защищенный сервер и ограничивайте доступ к каждому репозиторию (например, с помощью gitosis, а можно и просто юникс-средствами ограничить доступ к определенным директориям на сервере).
Какое-то феодальное восприятие. Сотрудник, ценящий свою работу и себя, может всегда быть в поиске работы. Ровно как работодатель — всегда в поиске новых, лучших, сотрудников. Нервничать нужно когда производительность падает или настроение ухудшается.
Народ уже давно собирается там и выкладывает плагины, патчи и документацию на вики-страницах.
Секция «Protocol Overview (opinions for all)»
Вот это мне и интересно. Чем руководствуются авторы политики защиты private-переменных от инсайдеров. Наличием злобных инсайдеров?
>> Язык предоставляет право выбора механизма и политики, а так же право смешивать их. <<
разумно
К инкапсуляции и ооп мое любопытство не имеет прямого отношения.