Сегодня в microsoft study-group обсуждали стринг. Собственно эта тема всех интервью - что нужно использовать для "оптимального" хранения строчек? И все хором говорят - используем StringBuilder. А на вопрос, что использовать для кокатации строк - String.Format. И все напрочь забывают, что мы программируем не для оптимизации, а для того, чтобы поддерживать код и развивать. То есть делать код понятным даже первокласснику, что не скажешь про "профессионально" оптимизированные без надобности куски творчества.
Так вот про вопросы интервью. Я с ними полностью не согласен. Люди! Не то чтобы на пороге 21 век, он уже дома! Преждевременная оптимизация - зло и порождает ДОРОГОСТОЯЩИЙ код! Качественный код приравнивается к самодокументируемому коду. Оптимизация здесь не рассматривается - она здесь не обсуждается. Так как мы бизнес-разработчики, а не любители оптимизнуть что под руку попадёт. Бизнес-разработчик пишет код, где каждая строчка отражает НАМЕРЕНИЕ, а не хитро-вычитанные фичи платформы :)
Начну развеивать заблуждение с конкатацией через String.Format. Цель функции String.Format форматирование строки, а не конкатация. То есть привращать 1 в 001,00 например. С точки зрения качественного программирования запись с целью конкатации String.Format("Total: {0} dollars", total); выглядит настолько неэкономично, что ужас. Конечно микроскопом можно гвозди забивать :) У некоторых это даже получается. Во-первых, чтобы понять это, нужно чтение слева-направа заменить на скачкообразное чтение с актвацией ячейки памяти в моём мозгу. Во-вторых, добавление новых переменных вызывает дополнительное напряжение - теряем время, за которое нам платят деньги. В-третьих, чтобы добавить новую переменную - мне нужно делать 2 (!!!!) изменения.
Исходя из этих соображений. А мои соображения основываются на принципах Implementation Patterns & Refactoring и трёх простых ценностях (коммуникация, простота и гибкость). В данном случае используем самую первую и самую важную ценность - коммуникация. Напомню: Коммуникация (communication) - разрабатываемый код должен явно отражать намерение создателя. Этот принцип подчёркивается и в рефакторинге. Так вот начиная читать строку String.Format - я чётко фиксирую себя на мысле "форматируем"!, а когда плюсиками - то конкатируем. Просто и разумно.
Ужасная конкатация через форматирование: String.Format("Total: {0} dollars", total);
Поэтому намного лучше и приятней: "Total: " + total + " dollars";
Хотя, перед PHP код снимаю шляпу: echo "Total: $total dollars";
Все сразу начинают вспоминать эффективность и оптимизацию. Не знаю, что пишут в современных книжках. Но я читал книги 1970-х годов, ещё в то время писали - "народ у нас мощные компы, бросьте оптимизаций заниматься заранее, делаете более читаемый и хьюмэн ориентед код". И это писал практик, а чуть ранее теоретик программирования Кнут писал тоже самое :)
К вопросу о StringBuilder - это ещё та тема. Все вертится вокруг сборки результата, результирующего значения. Объект выполняет роль сборщика. В одном месте мы собираем данные, а в другом потребляем. Это не форматирование и не простая конкатация. А целый алгоритм конкатации. Поэтому использование предыдущих методов, когда нужен StringBuilder, обречёт наследников вашего кода вспоминать вас недобрым словом :)
Итак с точки зрения качественного кода (а это код, которых легко читать):
StringBuilder - вещь хорошая, но его стоит применять, когда мы подходим к объекту как механизму с накапливанием значения, а результат будет снят как сливки намного дальше от кода наполнения. То есть в одном месте явно накапливаем (сложный код... преимущественно бывает в циклах), а в другом вы забираете результат (особенно часто встречается со словом return ;).
String.Format - для форматирования кода, но не конкатации. Причем в отличие от String.Builder результат забирается в месте форматирования.
+ (любимый плюсик для строк) - приятный и дешевый способ конкатации
PS. "Экономично", "дорогостоящий" и "дешевый" читать с точки зрения разработки и поддержки. Меньше тратим время, чтобы "врубиться", значить дешевле. Время - деньги.
PS2. А оптимизация делается на заключительной стадии. Ключевое слово: профайлер.
понедельник, 20 апреля 2009 г.
String vs StringBuilder
Подписаться на:
Комментарии к сообщению (Atom)
String.Format("Total: {0} dollars", total) куда понятнее и легкомодифицируемо, чем "Total: " + total + " dollars"
ОтветитьУдалитьЯ не соглачен, что второй вариант 'намного лучше и приятней'. Это неудачный пример на мой взгляд.
x = String.Format("Total: {0} dollars", total);
ОтветитьУдалитьx = "Total: " + total + " dollars";
Форматирование и даже здесь проявляется. Два пробела - по мне смотрятся как часть форматирования. Поэтому прийдётся пересматривать концепт :D
Но расположив две строчки вместе я понимаю, читать слева направа без лишних вещей (String.Format, {0} и ещё скобочки) намного проще. Хотя есть другие значки. Да ещё и букв меньше. Не находишь?
Ваш метод прекрасен, но до того момента, как вам понадобится указывать адвансед форматтинг -- например, число знаков после запятой, прижаться или нет к левому краю, знак результата, символ ден единицы. и т.п. Вот тут и начнутся танцы с бубнами.
ОтветитьУдалить>> Хотя, перед PHP код снимаю шляпу
Кстати, В Boo есть интерполяция строк :) Кстати, весьма agile-истый язык, нет личшних '{' и '}'.
-- meowth
А дай пример из Boo.
ОтветитьУдалитьКак только форматинг, а особенно продвинутые вещи, то я уже для этого делаю спец.классы или атрибуты начинаю добавлять. Но это тема другого разговора. Кстати, можно объединить усилия и написать статью на эту тему. Я тут чуток слабоват в форматингах, но зато могу оценить с точки зрения качества :)
Под "точка зрения качества" я понимаю применение ряда ценностей и принципов написания кода. Должно выйти неплохо.
Не вопрос :) По примеру Выше -- интерполяция "долларов"
ОтветитьУдалить[code]
dollars = 100M
result = "Total ${i} dollars"
x as string = "hmm?"
x = "ok, it's really 100" if result = "Total 100 dollars"
print x
[/code]
-- meowth
Битва за употребление String и StringBuilder - это битва за производительность. Попробуйте замерить скорость исполнения for(int i = 0; i < 10000; i++) (1)s += "Hello"; (2)s.Append("Hello"); И будет сразу понятно когда употреблять String а когда StringBuilder.
ОтветитьУдалитьПреждевременное поднятие вопроса оптимизации - зло. Согласен?
ОтветитьУдалитьПреждевременное ... - зло. Согласен.
ОтветитьУдалитьНо если в коде фигурирует конструкция i<10000, то можно и преждевременно задуматься об оптимизации.
Профайлер должен думать, а не я.
ОтветитьУдалитьЯ должен думать о воплащение моей бизнес-мысли в коде. Именно воплащенная бизнес-мысль в коде ведёт к качественному коду. А не мысль-оптимизация.
Кстати в твоём примере StringBuilder нужно использовать не по причине оптимизации, а по той, которая упомянута у меня в исходном сообщение.
Кстати, судя по твоим комментариям, ты предполагаешь, что я не знаю твоих аргументов? :) Твои аргументы стандартные фразы в любом учебнике по C#. Мои мысли уникальны. Они рождены на стыке TDD + Refactoring + Implementation Patterns и рассматриваемых классов C#.
ОтветитьУдалитьТы ничего нового, к сожалению не высказал. Да к тому же своими вопросами показываешь своё предположения, что я не читал стандартных учебников C# (Троелсена, Рихтера и msdn).
Но другой вопрос - а понял ли ты мои мысли? Сможешь ли ты их использовать? Почему я предложил такие идеи? Что за ними лежит? Какие ценности и принципы они отражают?
easy, easy ...
ОтветитьУдалитьКонечно понял, даже написал "Преждевременное ... - зло. Согласен.
", что ж тут не понятного. Все мои комменты - не попытка выставить в неприглядном свете.
Тем не менее, может иногда стоит думать на шаг вперёд, если решение столь очевидно. Возможно это и есть стандартные фразы из любого учебника по С#. Более того, думаю, что MSDN - настольная книга .NET разработчика. Что ж тут плохого.
Мысли твои не понял (не умею их читать), а что написано в статье - понял. И до этой статьи использовал принцип, что не стоит оптимизировать без надобности.
На этом стоит закончить, иначе коммент превратится в о флуд.
То есть, ты на мои вопросы не ответишь :)
ОтветитьУдалитьМногоуважаемый Денис, я тут бегло пробежался по комментариям:
ОтветитьУдалить1. Скажите какой у вас был стаж работы непосредственным разработчиком, тем кто практически целый день пишет код.
2. Судя по некоторым вашим комментариям у меня закралось подозрение что у вас мания величия, нужно как-то более уважительнее, или уж так сказать снисходительнее относитсья к людям которые заходят на ваш блог.
3. Так как разгорелась такая дискуссия по поводу статьи, то утверждать что 'очевидно' что-то зло, а вот это 'правильно' нет никаких оснований - в противном случает получается, что либо вы плохо изложили свою идею, либо просто все тупые бараны кто не соглашается.
Сергей, а можно узнать причины твоего "многоуважения" :)
ОтветитьУдалить1. с 2001 года и им остаюсь
2. это лишь твои оценочные подозрения
3. ну по себе других не судят :)
любое зло я аргументирую и если у тебя есть недопонимание или вопросы - спрашивай буду отвечать в меру своей распущенности :) а если другое мнение - всегда пожалуйста, а иначе флейм ориентированный на личность, а не на качество.
Кстати, дискуссия не разгорелась. Были попытки вспомнить стандарные учебники и только. К сожалению ожидаемый мною уровень обсуждений не был достигнут. Жаль.
ОтветитьУдалитьЗЫ. Но оставленные комменты тоже показывают уровень, к которому нужно довести статью. За такую "косвенную" помощь и соавторство тоже спасибо.