Делаем классы Objective-C красивыми - PullRequest
37 голосов
/ 09 декабря 2010

Я хотел бы спросить всех вас о мнениях о запахах кода в Objective C, в частности, Cocoa Touch. Я работаю над довольно сложной игрой и собираюсь начать рефакторинг Великого декабря.

Многие мои классы, в частности модели, полны методов, которые имеют дело с внутренней бизнес-логикой; Я буду скрывать это в частной категории, в моей войне с массивными заголовочными файлами. Эти частные категории содержат большое количество объявлений, и это заставляет меня чувствовать себя неловко ... почти как в Objective-C, чтобы заставить меня чувствовать вину за все эти методы.

Чем больше я занимаюсь рефакторингом (хорошо!), Тем больше мне приходится поддерживать все это дублирование (не очень хорошо). Это просто неправильно.

На таком языке, как Ruby, сообщество уделяет большое внимание очень коротким, ясным и красивым методам. У меня вопрос, для Objective C (в частности, Cocoa Touch), как долго ваши методы, насколько велики ваши контроллеры, и сколько методов на каждый класс вы найдете в своих проектах? Есть ли в Objective C какие-нибудь особенно хорошие, красивые примеры классов, составленных из коротких методов, или это просто не важная часть языковой культуры?

РАСКРЫТИЕ ИНФОРМАЦИИ: В настоящее время я читаю "Маленький интриган", который должен объяснить мою грусть, относительно: Цель С.

Ответы [ 3 ]

15 голосов
/ 09 декабря 2010

Красота субъективно. Для меня класс Objective-C прекрасен, если он читабелен (я знаю, что он должен делать) и поддерживается (я могу видеть, какие части за что отвечают). Мне также не нравится, когда меня читают из-за незнакомой идиомы. Вроде как, когда вы читаете книгу и читаете что-то, что выводит вас из погружения и напоминает, что вы читаете.

Возможно, вы получите много разных, взаимоисключающих советов, но вот мои мысли.

  • Нет ничего плохого в том, что частные методы находятся в частной категории. Вот для чего это. Если вам не нравятся объявления о засорении файла, либо используйте свертывание кода в IDE, либо добавьте свои расширения в качестве категории в другой файл.
  • Группируйте связанные методы вместе и пометьте их #pragma mark операторами
  • Независимо от того, какую схему кода вы используете, важна согласованность. Потратьте несколько минут и напишите свои собственные правила (здесь мое ), поэтому, если вы забудете, что должны делать, у вас есть справка.
  • Контроллер не должен быть делегатом и источником данных, для них всегда могут быть другие классы.
  • Использовать описательные имена для методов и свойств. Да, вы можете задокументировать их, но вы не можете видеть документацию, когда Xcode применяет завершение кода, где хорошо названные методы и свойства окупаются. Кроме того, комментарии кода становятся устаревшими, если они не обновляются, а сам код изменяется.
  • Не пытайтесь писать умный код. Вы можете подумать, что лучше объединить последовательность вызовов методов в одну строку, но компилятор лучше оптимизирует, чем вы думаете. Можно использовать временные переменные для хранения значений (в основном это просто указатели, так что они относительно малы), если это улучшает читабельность. Напишите код для людей, который будет читать .
  • DRY применяется к Objective-C так же, как и к другим языкам. Не беспокойтесь о рефакторинге кода в другие методы. Нет ничего плохого в том, чтобы иметь много методов, если они полезны.
7 голосов
/ 12 декабря 2010

Самое первое, что я делаю еще до реализации класса или метода, это спрашиваю: «Как бы я хотел использовать это извне?»

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

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

Некоторые общие правила для любого языка или среды:

  • Следуйте своим интуитивным чувствам по любым советам, которые вы прочитали или услышали!
  • Спасайся рано!
    • При необходимости, проверить входные данные заранее и быстро выручить! Меньше очистки, чтобы сделать.
  • Никогда не добавляйте в свой код то, что вы не используете.
    • Опция для "реверс" может показаться чем-то приятным в будущем.
    • В этом случае добавьте это в будущем! Не тратьте время на добавление сложности, которая вам не нужна.
  • Имена методов должны описывать, что сделано, никогда , как это делается.
    • Методы должны иметь возможность изменять свою реализацию без изменения их имени, если результат одинаков.
    • Если вы не можете понять, что метод делает по его имени, измените имя!
    • Если часть достаточно сложна, используйте комментарии для описания своей реализации.
  • Не бойся одиночек!
    • Если в вашем приложении только одна модель данных, то это одиночная модель!
    • Обсуждая одну переменную повсеместно, вы просто притворяетесь, что это что-то еще, кроме одиночки, и добавляете сложность в качестве бонуса.
  • Планируйте сбои с самого начала.
    • Всегда используйте для doFoo:error вместо doFoo: с самого начала.
    • Создание хороших NSError экземпляров с локализованными описаниями для конечного пользователя с самого начала.
    • Серьезную боль представляет модернизация обработки ошибок / сообщений для большого существующего приложения.
    • И всегда будут ошибки, если у вас есть пользователи и IO!
  • Какао / Objective-C имеет значение Объект * Ориентирован, а не ** Класс Ориентирован как большинство популярных детей, которые утверждают, что являются ООП.
    • Не вводите класс немых значений только с свойствами, класс без методов, выполняющих реальную работу, также может быть структурой.
    • Пусть ваши объекты будут разумными! Зачем добавлять новый класс FooParser, если метод fooFromString: для Foo - это все, что вам нужно?
  • В Какао то, что вы можете сделать всегда важнее того, чем вы являетесь .
    • Не вводите протокол, если цель / действие могут это сделать.
    • Не проверять, что экземпляры соответствуют протоколам, это своего рода класс, который зависит от компилятора.
2 голосов
/ 09 декабря 2010

Мои 2 цента:

  1. Свойства обычно лучше, чем в старом стиле getter + setter.Даже если вы используете свойства @dynamic - объявляйте их с помощью @property, это намного информативнее и короче.
  2. Я лично не симулирую "частные" методы для классов.Да, я могу написать категорию где-нибудь в файле .m (m), но, поскольку у Obj-C нет чистого способа объявить закрытый метод - зачем мне его изобретать?В любом случае, даже если вам действительно нужно что-то подобное - объявите отдельный «MyClassPrivate.h» с категорией и включите его в файлы .m (m), чтобы избежать дублирования объявлений.
  3. Binding .Привязка для большинства отношений пользовательского интерфейса Controller <->, использование преобразователей, форматеров, просто не пишите методы для чтения / записи значений элементов управления вручную.Это делает код похожим на что-то из эпохи MFC.
  4. C ++ , большая часть кода выглядит намного лучше и короче при написании на C ++.Поскольку компилятор понимает классы C ++, это хороший момент для рефакторинга, особенно когда работает низкоуровневый код.
  5. Я обычно делю большие контроллеры.Что-то более 500 строк кода - хороший кандидат на рефакторинг для меня.Например, у меня есть контроллер окна документа, так как в некоторых версиях приложения он расширяет возможности импорта / экспорта изображений.Контроллер растет до 1.000 строк, где 1/2 - это «изображение».Это «триггер» для меня, чтобы создать ImageStuffController, создать его экземпляр в NIB и поместить туда весь код, относящийся к изображению.

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

...