Все знают, что при сложении строк в цикле правильно использовать StringBuilder вместо простого сложения строк, но иногда я вижу в коде очень занятные способы реализации этой идеи:
StringBuilder sb = new StringBuilder();
sb.Append("id="+id.ToString()+".");
Конечно, StringBulder тут используется, но толку от него не очень много. Правильный способ:
sb.AppendFormat("id={0}.", id);
Friday, November 19, 2010
Удаление каталога со всеми вложенными подкаталогами
Я видел в коде множество самых различных вариантов удаления каталога вместе с подкаталогами. Самый приличный из них был рекурсивный вызов удаления. Были и более забавные, например, запуск внешнего процесса "del folder -y".
На самом деле все проще - у метода System.IO.Directory.Delete есть второй параметр:
Delete(string path, bool recursive)
Если параметр recursive равен true, то каталог удаляется со всеми вложенными подкаталогами и файлами. Все просто.
На самом деле все проще - у метода System.IO.Directory.Delete есть второй параметр:
Delete(string path, bool recursive)
Если параметр recursive равен true, то каталог удаляется со всеми вложенными подкаталогами и файлами. Все просто.
Разница между Convert.ToInt32 и Int.Parse
Результат Convert.ToInt32 и Int.Parse будут различаться в случае передачи null. В первом случае результат будет равен 0, во втором - будет исключение. Это может оказаться существенным, например, если aspx-страница принимает параметр id, который преобразуется из строки в индекс объекта:
int id = Convert.ToInt32(Query["id"]);
При отсутствии параметра в этом случае будет отображаться объект с индексом 0 или может быть мы получим null reference exception. Это не очень хорошо. Правильнее - получить исключение, обработать его и сообщить пользователю об отсутствии необходимого параметра. А, следовательно, в этом случае правильнее использовать Int.Parse.
Тоже самое касается использования int.TryParse. Используйте его только в том случае, если знаете как будете обрабатывать результат ошибки преобразования.
int id = Convert.ToInt32(Query["id"]);
При отсутствии параметра в этом случае будет отображаться объект с индексом 0 или может быть мы получим null reference exception. Это не очень хорошо. Правильнее - получить исключение, обработать его и сообщить пользователю об отсутствии необходимого параметра. А, следовательно, в этом случае правильнее использовать Int.Parse.
Тоже самое касается использования int.TryParse. Используйте его только в том случае, если знаете как будете обрабатывать результат ошибки преобразования.
Wednesday, November 17, 2010
Не путайте разметку и код
Архитектура веб-страницы в ASP.NET предполагает разделение разметки и кода, но очень часто это правило нарушается. Например, приветствие выводится так:
txtWelcome.Text = string.Format("Здравствуйте <b>{0}/<b>", userFullName);
Или даже формируется целый блок html-кода внутри cs-файла. Такой подход очень неудобен.
Во-первых, поменять разметку и сообщение становится затруднительным - вполне вероятно придется перекомпилировать проект. Во-вторых, в aspx-разметку (которая может быть сделана либо с помощью css либо просто с помощью html-тегов) вмешивается разметка, приходящая из cs-файла, что может дать совсем не ожиданный результат. В-третьих, даже отладив всю разметку есть вероятность, что однажды возникнет необходимость ее поменять. А вот тут разработчиков и дизайнеров ждет сюрприз - часть разметки зашита в cs-код. Особенно дизайнеры радуются :)
Я рекомендую никогда не смешивать разметку и код. В случае отображения сообщения в aspx‑файле можно хранить полностью метку приветствия:
Здравствуйте, <b><asp:Label ID="lblWelcom" runat="server" /></b>
А в cs-файле присваивать значение поля lblWelcom.Text.
Либо, если есть такая необходимость, записывать значение метки вместе с указателями параметров и форматированием:
<asp:Label ID="lblWelcom" runat="server" Text="Здравствуйте, {0}" />
Но тогда при форматировании этой строки использовать ее саму как параметр функции форматирования:
lblWelcom.Text = string.Format(lblWelcom.Text, "Иван Иванович");
Такой код заменит параметры в метке и отобразит правильное сообщение, но оставит само сообщение в aspx-файле, а код работы с данными в cs-файле.
Условное отображение внутри Repeater
Задача заключается в том, чтобы отобразить часть данных внутри Repeater в зависимости от отображаемых данных. Например, нужно добавить кнопки действий в зависимости от некоторого поля Status. Самый простой вариант – использовать для этого специальный метод, примерно так:
<asp:Repeater ID="NotesRepeater" runat="server">
<HeaderTemplate>
<table class="list">
</HeaderTemplate>
<ItemTemplate>
....................................
<%# GetButtonHTML(Eval("Status"))%>>
....................................
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
А метод GetButtonHTML описывается внутри кода страницы так:
public string GetButtonHTML(object status)
{
Тут возвращаем HTML-код кнопки, проверяя status
return “<button style=”ActionButtonStyle”>Удалить</button>”;
}
Метод плох тем, что в нем смешивается разметка и код, т.к. часть разметки попадает в код. Это мешает работе дизайнеров, усложняет изменение кода.
Мне понравится другой вариант, чуть более сложный, но зато четко разделяющий код и разметку.
Разметку, зависящую от некоторых условий, оборачиваем в PlaceHolder, а в сам элемент Repeater добавляем обработчик создания элементов:
<asp:Repeater ID="NotesRepeater" runat="server"
OnItemDataBound="NotesRepeater_ItemDataBound">
<HeaderTemplate>
<table class="list">
</HeaderTemplate>
<ItemTemplate>
....................................
<asp:PlaceHolder ID="ActionHolder"
Visible="false" runat="server">
<button style=”ActionButtonStyle”>Удалить</button>
</asp:PlaceHolder>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
В обработчике создания элементов устанавливаем видимость ActionHolder в зависимости от нужных условий:
protected void NotesRepeater_ItemDataBound(object sender,
RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
Note item = e.Item.DataItem as Note;
if (item == null)
return;
Control actionHolder =
e.Item.FindControl("ActionHolder");
actionHolder.Visible = item.Status == 0;
}
}
Теперь код живет сам по себе, а разметка сама по себе. Что и хотелось.
Monday, November 15, 2010
Разработка ПО как процесс
Самое приятное дело – писать код “для себя”. К сожалению, есть одна проблема – получить денег за это не получится. По крайней мере, не получится получать деньги постоянно и регулярно (допускаю, что продать код, написанный “для себя” один-два раза получится).
Что же отличает разработку для собственного удовольствия от промышленной разработки ПО? Да примерно то же самое, что отличает мастера-горшечника от промышленного автомата, штампующего чашки и тарелки. Во-первых, это объем. Одно дело, написать одну программу за год-два. Другое – делать это постоянно. Хорошо если у мастера есть имя и его продукция расходится по баснословной цене, покрывающей все его расходы на несколько лет вперед. А если нет? Да и конкуренты не дремлют… Во-вторых, это Заказчик. Для себя можно долго “дотачивать” продукт до совершенства. Но Заказчик хочет получить не только качественный продукт, но и получить его к определенному сроку и за определенную (часто оговоренную заранее) цену. В-третьих, это команда. Небольшую программу можно создать одному, но сделать большую, многофункциональную систему (например, MS Office) одному и в разумный срок не получится.
Итого, можно сформулировать такие цели разработки ПО:
1. Получение прибыли.
a. Программу нужно разработать в определенный срок. Заказчик не захочет ждать “вот как только допишем, сразу отдадим”. Заказчик готов ждать, но ждать понятный и разумный срок. Да и увеличение срока будет увеличивать расходы на разработку программы (зарплата, офис, оборудование) и эти расходы “съедят” всю прибыль.
b. Программу нужно разработать в определенный бюджет, причем, часто бюджет оговаривается на самой начальной стадии. Другими словами, процесс разработки должен быть стандартизирован так, чтобы затраты можно было предсказать до начала разработки.
2. Заказчик должен быть доволен
a. Программа должна решать проблему Заказчика. Иначе он просто не будет ей пользоваться. Даже если мы получим за это денег, то он к нам больше не вернется и не приведет новых клиентов.
b. Программа должна быть качественной. Если программа работает, но постоянно “падает”, то сомнительно, что Заказчик будет доволен.
c. Заказчик должен захотеть заказывать новую функциональность именно у нас. Такая доработка должна иметь разумную цену и не быть завышенной. Довольный Заказчик приведет новых клиентов.
3. Команда должна быть довольна
a. Если в процессе разработки команда разбежалась, то кто будет дорабатывать продукт и приносить новую прибыль?
b. Если продукт настолько некачественно написан, что понять код могут только те, кто его написал, то проблемы в доработке обеспечены – рано или поздно “старикам разработки” этот продукт надоест, и они либо уволятся, либо попросятся на другой проект.
Каждый из этих трех пунктов важен. Отсутствие хотя бы одного означает не качественный проект и ставит под угрозу будущее компании-разработчика.
Почему нужно писать качественный код
Каждый слышал, что нужно писать “качественный код”. Но какой код считать качественным? Для кого-то качественный код это “работает и выдает результат”. Для кого-то “красивый, комментированный, использующий паттерны, ООП”. Если критерии качественно кода “спускаются сверху”, то затруднение вызывает вопрос – зачем собственно так писать? Ведь чаще всего по-быстрому проще и легче, чем качественно.
Не секрет, что мы пишем программы для того, чтобы заработать деньги. Это означает, что качественное ПО (программное обеспечение) это то, которое приносит больше денег.
Качественное ПО это то, которое приносит больше денег!
Давайте разберемся, как зарабатываются деньги в сфере разработки ПО. Подчеркиваем, мы будем говорить именно о разработке ПО, а не просто о написании кода для курсовой или лабораторной работы.
Типы производства
Существуют три основных типа производства ПО:
- Коробочное. Программа разрабатывается один раз (имеется ввиду одна версия программы), затем тиражируется множеством экземпляров и продается Покупателям (именно так – с большой буквы!). Функциональность продукта определяется разработчиками, возможно, с учетом пожеланий Покупателей.
- ПО под заказ. Компания пишет ПО под заказ конкретного Заказчика. Именно Заказчик определяет функциональность продукта и платит деньги за ее реализацию.
- Аренда. Компания пишет ПО и сдает его Клиентам в аренду в виде сервиса. Обычно это веб-приложения.
Прибыль
Прибыль вычисляется, как разница между затратами и полученными деньгами. Затраты это зарплата сотрудникам, налоги, оборудование, аренда офиса, обслуживание и т.д.
Деньги можно получить одним из трех вариантов:
- Деньги, полученные от продажи ПО.
- Деньги, полученные от Заказчика за сделанную работу.
- Деньги, полученные от Клиентов за аренду ПО.
Других вариантов нет.
Как увеличить прибыль
Очевидно, увеличить прибыль можно только двумя способами: уменьшить расходы или увеличить приход.
В случае коробочного ПО прибыль напрямую зависит от стоимости тиражируемой программы. Но увеличивать стоимость бесконечно нельзя - программу просто перестанут покупать, и Покупатели уйдут к более дешевым конкурентам. Значит нужно увеличивать число продаж, привлекать и удерживать Покупателей.
Как привлечь и удержать Покупателей? Конечно, важна и реклама и маркетинг, но мы пока обсуждаем этот вопрос с точки зрения разработки. Понятно, что продукт должен иметь хорошую функциональность, быть стабильным (не “падать”), быть достаточно гибким, но одновременно и простым в использовании.
Кроме того, нужно понимать, что продукт, скорее всего, не единственный на рынке и разработчики должны иметь возможность быстро и качественно добавлять в продукт новую функциональность. Иначе продукт будет отставать от конкурентов.
В случае с заказным ПО ситуация похожая. Получить существенно больше денег с Заказчика нельзя – на рынке много разработчиков и Заказчик может просто “уйти”, не согласившись с завышенными ценами на разработку. Значит нужно иметь больше Заказчиков. Другими словами, это означает: уметь разрабатывать быстро и качественно. В идеальном случае Заказчик придет еще раз, с новым заказом или заказом на доработку старого продукта, да еще и привлечет новых Заказчиков.
Сдача сервисов в аренду отличается не сильно. Точно так же необходимо создавать стабильное и гибкое ПО, необходимо уметь реагировать на новые требования. Реагировать быстро и качественно, без ошибок и сбоев.
А что такое некачественный код?
Если созданный продукт не решает задачу Заказчика, Клиента, Покупателя, то он не имеет смысла. Денег за него не получить.
Если продукт постоянно “падает”, работает медленно, пользователи теряют свои данные, то, в конце концов, они найдут другой, более качественный продукт и будут пользоваться им.
Если стоимость небольшой доработки программы будет сопоставима с полной переработкой всей программы – Заказчик будет недоволен и уйдет к другим, вменяемым разработчикам.
Если добавление новой функциональности поломает уже работающую, старую функциональность – это приведет к убыткам клиентов. Так простой одного рабочего дня банка из-за неработающего ПО может исчисляться миллионами рублей. Вам хочется получить счет на оплату убытков?
Если добавление новой функциональности занимает очень длительный срок, то конкуренты выйдут на рынок первыми и будут использовать свои преимущества.
Если добавление новой функциональности настолько сложно, что потребует тестирование всего продукта заново, то это означает повышение расходов на группу тестирования. А ведь эти расходы могли бы быть совсем небольшие…
Если код написан так, что не позволяет тестировать его в автоматическом режиме, обязательно требует наличия оператора (пользователя) у клавиатуры и монитора - это означает, что группа тестирования будет тестировать все снова и снова.
Что еще нужно учитывать
А еще нужно учитывать, что кроме себя любимого есть команда, которая работает над проектом. Большой проект, большую программу, не получится сделать одному человеку в разумный срок. Значит нужно учитывать, что:
- Вашим кодом будут пользоваться другие разработчики. Они должны его понимать и уметь использовать только так, как это задумывалось.
- Возможно, что программу начнут разрабатывать одни люди, а дорабатывать новую функциональность (ведь мы стремимся к тому, чтобы Заказчик пришел к нам снова и снова!) будут совсем другие люди. Чем меньше времени они потратят на “вход” в курс дела, тем меньше денег мы потратим.
Итого
Итак, что требуется от качественного кода:
- Скорость разработки
- Скорость добавления нового функционала
- Качество разработки, минимальное число ошибок
- Сохранение работающего функционала при добавлении нового
- Возможность быстрого понимания кода другими разработчиками
- Возможность тестирования программы в автоматическом режиме
Почему нужно писать качественный код? Потому что это деньги!
Subscribe to:
Posts (Atom)