Сегодня, 13 сентября - День программиста, который принято отмечать в 256 день года.
Долгое время не было единства, в том когда же все таки отмечать этот праздник. Нет его и сейчас. Некоторые предлагают 10 декабря, другие 19 июля. Но в последнее время большинство склоняется к этой дате.
Поздравляю всех тех, кто хоть раз в жизни заставлял оживать беспомощное электронное железо, подчиняясь написанной вами программе. Вы можете причислить себя к славному племени программистов, чьими незаметными стараниями так круто меняется вся сегодняшняя наша жизнь.
Сегодня вы определяете, насколько "умными" станут завтра телефоны и холодильники, светофоры и автомобили, и наконец, компьютеры. На кончиках ваших пальцев рождается образ будущего, и это замечательно.
С праздником вас, коллеги!
четверг, сентября 13, 2007
вторник, сентября 11, 2007
Это не web сервисы...
Web сервисы завоевали свое место под солнцем в инфраструктуре приложений масштаба предприятия. Теперь среди разработчиков и пользователей таких систем часто можно слышать диалоги вроде: "Нам нужны сводные данные по продажам из вашей системы. У вас нет подходящего web сервиса?". И часто подходящий сервис находится.
К сожалению, эти web сервисы зачастую сделаны так, что назвать их не то что "подходящими", но и "web сервисами" просто не поворачивается язык.
Вот пример (я использую псевдокод для описания контракта сервиса вместо WSDL, чтобы было понятнее):
Делать какие либо предположения, для чего предназначен метод CT() на основе его контракта абсолютно бесперспективное занятие. То же можно сказать и о выдаваемых им результатах. "Чтобы понять - надо жевать" - чтобы разобраться с результатами надо вызвать метод и вывести полученный XML на печать или экран, а затем читать его и думать что же делать дальше.
А вот, извините за выражение, стринговый контракт метода GetSales() по заверениям его разработчиков был разработан исключительно в целях кроссплатформенной совместимости. При этом, выяснились удивительные вещи. Оказалось что передавать даты можно только в формате "DD-MM-YY", любой другой приводит к падению сервиса. Результирующая строка содержит в себе довольно кучерявый XML в неизвестной кодировке, а при отсутствии продаж за период результат содержит (внимание!) строку вида: "There are not sales {имя офиса} for period".
Примеры подобного рода можно продолжать долго. Однако все это не web сервисы.
Факт, что Web сервисы на сегодня, это самый простой, быстрый и удобный способ организовать межпрограммное взаимодействие как на .NET так и на Java. И многие используют их именно как механизм удаленного вызова через SOAP over HTTP. И забывают при этом об основном отличие web сервисов от механизмов RPC - способности к само-описанию посредством метаданных представленных в WSDL.
WSDL описывает два важнейших аспекта сервиса: способ вызова методов (binding and ports) и формат передаваемых сообщений (message and types). В приведенных в качестве примера сервисах невозможно сказать, что либо определенное о формате их сообщений. Использование такого сервиса возможно только в комплекте с программистом его написавшим, а при недоступности последнего такие сервисы становятся совершенно бесполезны.
В общем, "сказка ложь, да в ней намек,/ добрым молодцам - урок". Урок прост:
- не используйте в сообщениях web сервисов XML не описанный в WSDL схеме сервиса;
- не используйте в сообщениях web сервисов строки вместо элементарных типов
- не используйте в сообщениях web сервисов строки для передачи произвольного XML;
- не используйте в web сервисах нетипизированные DataSet-ы;
- комментируйте контракты web сервисов, это как раз тот случай, когда комментариев много не бывает.
К сожалению, эти web сервисы зачастую сделаны так, что назвать их не то что "подходящими", но и "web сервисами" просто не поворачивается язык.
Вот пример (я использую псевдокод для описания контракта сервиса вместо WSDL, чтобы было понятнее):
[WebMethod]
public XmlNode CT(DateTime dateFrom);
или
[WebMethod]
public string GetSales(string from, string to, string office);
Делать какие либо предположения, для чего предназначен метод CT() на основе его контракта абсолютно бесперспективное занятие. То же можно сказать и о выдаваемых им результатах. "Чтобы понять - надо жевать" - чтобы разобраться с результатами надо вызвать метод и вывести полученный XML на печать или экран, а затем читать его и думать что же делать дальше.
А вот, извините за выражение, стринговый контракт метода GetSales() по заверениям его разработчиков был разработан исключительно в целях кроссплатформенной совместимости. При этом, выяснились удивительные вещи. Оказалось что передавать даты можно только в формате "DD-MM-YY", любой другой приводит к падению сервиса. Результирующая строка содержит в себе довольно кучерявый XML в неизвестной кодировке, а при отсутствии продаж за период результат содержит (внимание!) строку вида: "There are not sales {имя офиса} for period".
Примеры подобного рода можно продолжать долго. Однако все это не web сервисы.
Факт, что Web сервисы на сегодня, это самый простой, быстрый и удобный способ организовать межпрограммное взаимодействие как на .NET так и на Java. И многие используют их именно как механизм удаленного вызова через SOAP over HTTP. И забывают при этом об основном отличие web сервисов от механизмов RPC - способности к само-описанию посредством метаданных представленных в WSDL.
WSDL описывает два важнейших аспекта сервиса: способ вызова методов (binding and ports) и формат передаваемых сообщений (message and types). В приведенных в качестве примера сервисах невозможно сказать, что либо определенное о формате их сообщений. Использование такого сервиса возможно только в комплекте с программистом его написавшим, а при недоступности последнего такие сервисы становятся совершенно бесполезны.
В общем, "сказка ложь, да в ней намек,/ добрым молодцам - урок". Урок прост:
- не используйте в сообщениях web сервисов XML не описанный в WSDL схеме сервиса;
- не используйте в сообщениях web сервисов строки вместо элементарных типов
- не используйте в сообщениях web сервисов строки для передачи произвольного XML;
- не используйте в web сервисах нетипизированные DataSet-ы;
- комментируйте контракты web сервисов, это как раз тот случай, когда комментариев много не бывает.
вторник, сентября 04, 2007
Секреты отладки
Отладка, самая сложная и пожалуй самая увлекательная часть работы программиста. Вы так не считаете? Тогда, вам стоит подумать о переходе в менеджеры.
К сожалению, премудростям отладки нигде не учат. Но к счастью есть люди, которые постигли этот путь в совершенстве. С одним из них - Андрем Бороздиным мне посчасливилось работать, а сегодня я рад представить вам его блог "Будни программиста" и интересный материал "Установка брейкпоинтов в управляемом коде без исходников" . Хороший материал. Так держать!
К сожалению, премудростям отладки нигде не учат. Но к счастью есть люди, которые постигли этот путь в совершенстве. С одним из них - Андрем Бороздиным мне посчасливилось работать, а сегодня я рад представить вам его блог "Будни программиста" и интересный материал "Установка брейкпоинтов в управляемом коде без исходников" . Хороший материал. Так держать!
понедельник, сентября 03, 2007
Об опасности дефолтных значений
Программисты любят дефолтные значения. Они, собственно их и выдумали. Для программиста слово дефолт ласкает слух, у всех других оно вызывает самые неприятные ассоциации (дефолт рубля, большой дефолт 1998 года...). Но неприятности с дефолтами бывают и у программистов.
Жила была одна система. Среди прочего, она обрабатывала некие задачи. Задачи хранились в БД и были у этих задач состояния. В системе эти состояния были представлены перечислением (enum), а в БД, соответственно - числом (int):
Как известно, в C# тип enum может базироваться на любом из базовых перечислимых типов, а по умолчанию для этого используется Int32. Если значения enum не указаны явно, то первому соответствует 0, второму 1 и т.д.
Но вот в один прекрасный день, в системе решили сделать улучшение - добавить возможность приостановки выполнения заданий. В перечисление добавили еще одно значение TaskState.Suspended, а в бизнес логику соответствующие методы:
Разрушительный эффект от этих нехитрых действий был потрясающий. В системе неожиданно возникла масса заданий в состоянии Rejected, а тысячи завершенных заданий (Completed) исчезли. Оно и понятно, если раньше состоянию Completed соответствовало число 3, то теперь оно соответствует состоянию Rejected. Самое смешное, что все модульные тесты прошли успешно.
Горячие головы уже спешно писали набросок скрипта для конвертации данных при переходе на новую версию, а всего то надо было явно объявить значения перечисления:
Жила была одна система. Среди прочего, она обрабатывала некие задачи. Задачи хранились в БД и были у этих задач состояния. В системе эти состояния были представлены перечислением (enum), а в БД, соответственно - числом (int):
public enum TaskState
{
//Ожидает
Waited,
//Назначена и исполняется
Assigned,
//Отклонена
Rejected,
//Завершена
Completed
}
public class Task
{
public TaskState State;
}
Как известно, в C# тип enum может базироваться на любом из базовых перечислимых типов, а по умолчанию для этого используется Int32. Если значения enum не указаны явно, то первому соответствует 0, второму 1 и т.д.
Но вот в один прекрасный день, в системе решили сделать улучшение - добавить возможность приостановки выполнения заданий. В перечисление добавили еще одно значение TaskState.Suspended, а в бизнес логику соответствующие методы:
public enum TaskState
{
//Ожидает
Waited,
//Назначена и исполняется
Assigned,
//Приостановлена
Suspended,
//Отклонена
Rejected,
//Завершена
Completed
}
public class Task
{
public TaskState State;
public void Suspend(){...}
public void Resume(){...}
}
Разрушительный эффект от этих нехитрых действий был потрясающий. В системе неожиданно возникла масса заданий в состоянии Rejected, а тысячи завершенных заданий (Completed) исчезли. Оно и понятно, если раньше состоянию Completed соответствовало число 3, то теперь оно соответствует состоянию Rejected. Самое смешное, что все модульные тесты прошли успешно.
Горячие головы уже спешно писали набросок скрипта для конвертации данных при переходе на новую версию, а всего то надо было явно объявить значения перечисления:
public enum TaskState
{
//Ожидает
Waited = 0,
//Назначена и исполняется
Assigned = 1,
//Приостановлена
Suspended = 4,
//Отклонена
Rejected = 2,
//Завершена
Completed = 3
}
Как вытащить иконку из ресурса
Недавно спрашивали у меня subj. Поскольку с формами я давненько не работал пришлось порыться в запасниках старого кода.
Итак, сначала, как внедрить иконку в ресурс сборки. Нет ничего проще. Добавляете файл иконки в проект Visual Studio. В свойствах файла меняете значение "Build action" на "Embeded resource". Все, при компиляции иконка будет добавлена как ресурс сборки.
Для того, чтобы извлечь иконку из ресурса используем метод Assembly.GetManifestResourceStream(string). Приведенный ниже код демонстрирует (а) как получить ссылку на сборку, (б) как извлечь иконку из ресурса сборки
Все очень просто. Сложности могут возникнуть с именем внедренного ресурса. Студия формирует имя ресурса так: берется Default Namespace, указанный в свойствах проекта и через точку добавляется имя файла. В крайнем случае, вы можете скомпилировать проект и затем открыть полученный .exe или .dll файл в ildasm.exe и посмотреть в манифесте сборки имя нужного вам ресурса.
Итак, сначала, как внедрить иконку в ресурс сборки. Нет ничего проще. Добавляете файл иконки в проект Visual Studio. В свойствах файла меняете значение "Build action" на "Embeded resource". Все, при компиляции иконка будет добавлена как ресурс сборки.
Для того, чтобы извлечь иконку из ресурса используем метод Assembly.GetManifestResourceStream(string). Приведенный ниже код демонстрирует (а) как получить ссылку на сборку, (б) как извлечь иконку из ресурса сборки
namespace ResourceIcon
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnShowIcon_Click(object sender, EventArgs e)
{
Assembly assembly = Assembly.GetAssembly(typeof(Form1));
//Assembly assembly = this.GetType().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("ResourceIcon.factory.ico"))
{
this.Icon = new Icon(stream);
}
}
}
}
Все очень просто. Сложности могут возникнуть с именем внедренного ресурса. Студия формирует имя ресурса так: берется Default Namespace, указанный в свойствах проекта и через точку добавляется имя файла. В крайнем случае, вы можете скомпилировать проект и затем открыть полученный .exe или .dll файл в ildasm.exe и посмотреть в манифесте сборки имя нужного вам ресурса.
Подписаться на:
Сообщения (Atom)