Что лучше: написание функций или методы написания? Что стоит больше производительности? - PullRequest
3 голосов
/ 20 мая 2009

В настоящее время я принимаю некоторые решения для своего первого API-интерфейса target-c. Ничего особенного, просто небольшая помощь для себя, чтобы сделать вещи быстрее в будущем.

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

Итак, что я сделал:

1) Я создал два новых файла (.h, .m) и дал «классу» имя: SLUtilsMath, SLUtilsGraphics, SLUtilsSound и так далее. Я считаю это своего рода «пространством имен», поэтому все эти вещи всегда будут называться SLUtils ******. Я добавил их все в Group SL, который содержит подгруппу SLUtils.

2) Затем я просто помещаю сигнатуры своих функций в файл .h, а реализации функций - в файл .m. И угадайте, что: это работает! Я доволен этим, и им легко пользоваться. Единственная неприятность в том, что я должен включать соответствующий заголовок каждый раз, когда мне это нужно. Но это нормально, так как это нормально. Я мог бы включить его в файл pch префикса заголовка.

Но затем я пошел в туалет, и там появился призрак, сказавший: «Эй! Разве не лучше создавать реальные методы вместо функций? Разве вы не должны создавать классовые методы, чтобы вам приходилось вызывать метод, а не функция? Разве это не намного круче и не лучше? " Ну, для удобства чтения я предпочитаю функции. С другой стороны, у них нет таких «именованных параметров», как методы, a.f.a.i.k ..

Так что бы вы предпочли в этом случае?

Конечно, я не хочу выделять объект перед использованием полезного метода или функции. Это было бы мучительно.

Может быть, туалетный призрак был прав. Есть более крутой способ. Ну, лично для меня это здорово:

MYNAMESPACECoolMath.h

#import <Foundation/Foundation.h>


@interface MYNAMESPACECoolMath : NSObject {
}

+ (float)randomizeValue:(float)value byPercent:(float)percent;

+ (float)calculateHorizontalGravity:(CGPoint)p1 andPoint:(CGPoint)p2;

// and some more
@end

Затем в коде я просто импортировал бы этот MYNAMESPACECoolMath.h и просто вызвал:

CGFloat myValue = [MYNAMESPACECoolMath randomizeValue: 10.0f byPercent: 5.0f];

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

Преимущество перед функцией, насколько я заметил, заключается в лучшей читаемости кода. Когда вы смотрите на CGRectMake (10.0f, 42.5f, 44.2f, 99.11f), вам, возможно, придется посмотреть, что означают эти параметры, если вы не очень знакомы с ним. Но когда у вас есть вызов метода с «именованными» параметрами, вы сразу видите, что это за параметр.

Я думаю, что упустил момент, который имеет большое значение для одноэлементного класса, когда речь идет о простых полезных методах / функциях, которые могут понадобиться везде. Создание специального вида случайных значений ни к чему не относится, оно глобально. Как трава. Как деревья. Как воздух. Это нужно всем.

Ответы [ 5 ]

6 голосов
/ 20 мая 2009

С точки зрения производительности метод static в классе static компилируется почти так же, как функция.

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

Что касается предпочтения или читабельности, то существует тенденция использовать статические методы чаще, чем необходимо, потому что люди смотрят, что Obj-C - это только OO-язык, такой как Java или C #. В этой парадигме (почти) все должно принадлежать классу, поэтому методы класса являются нормой. На самом деле они могут даже называть их функциями. Два термина взаимозаменяемы там. Однако это чисто условно. Конвенция может быть даже слишком сильным словом. Нет ничего плохого в том, чтобы использовать функции вместо них, и, вероятно, более уместно, если нет элементов класса (даже статических), которые необходимы для помощи в обработке этих методов / функций.

5 голосов
/ 20 мая 2009

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

Вместо того, чтобы разбираться в том, как упаковать служебные функции, вы должны подумать о том, над какими объектами модели должны работать эти функции, а затем поместить их в эти классы (создавая классы, если это необходимо).

По словам Джоша, хотя в ObjC нет ничего плохого в функциях, это очень сильно объектно-ориентированный язык, основанный непосредственно на дедушке объектно-ориентированных языков, Smalltalk. Вы не должны слегка отказываться от шаблонов ООП; они - сердце Какао.

Я все время создаю частные вспомогательные функции и создаю общедоступные вспомогательные функции для некоторых объектов (хорошим примером этого является NSLocalizedString ()). Но если вы создаете общедоступные функции полезности, которые не являются интерфейсом для методов, вы должны переосмыслить свои шаблоны. И первым предупреждающим знаком является желание вставить слово «util» в имя файла.

EDIT

Исходя из конкретных методов, которые вы добавили в свой вопрос, вы должны искать категории. Например, +randomizeValue:byPercent: - это очень хорошая категория NSNumber:

// NSNumber+SLExtensions.h
- (double)randomizeByPercent:(CGFloat)percent;
+ (double)randomDoubleNear:(CGFloat)percent byPercent:(double)number;
+ (NSNumber *)randomNumberNear:(CGFloat)percent byPercent:(double)number;

// Some other file that wants to use this
#import "NSNumber+SLExtensions.h"
randomDouble = [aNumber randomizeByPercent:5.0];
randomDouble = [NSNumber randomDoubleNear:5.0 byPercent:7.0];

Если вы получаете много из них, то вы можете разделить их на такие категории, как NSNumber + Random. Однако выполнение этого с категориями делает его прозрачной частью существующей объектной модели, а не создает классы, единственной целью которых является работа с другими объектами.

1 голос
/ 20 мая 2009

Когда речь идет о производительности методов и функций, у Майка Эша есть несколько замечательных цифр в его посте «Сравнение производительности обычных операций» . Операции отправки сообщений в Objective-C чрезвычайно быстры, настолько, что вам понадобится действительно жесткий вычислительный цикл, чтобы увидеть разницу. Я думаю, что использование функций и методов в вашем подходе сводится к проблемам стилистического дизайна, которые описывали другие.

1 голос
/ 20 мая 2009

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

Нет ничего плохого в использовании простых функций Си. Просто знайте, что вы не сможете передать их, используя @selector для таких вещей, как executeSelectorOnMainThread.

0 голосов
/ 21 мая 2009

Оптимизируйте систему, а не вызовы функций.

Реализуйте то, что легче всего понять, а затем, когда вся система работает, профилируйте ее и ускорьте то, что медленно. Я очень сомневаюсь, что накладные расходы времени выполнения c-класса статического класса будут иметь значение для всего вашего приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...