Показаны сообщения с ярлыком программирование. Показать все сообщения
Показаны сообщения с ярлыком программирование. Показать все сообщения

четверг, 1 августа 2013 г.

Мысли вслух, или не могу больше молчать


Отправили мое резюме в одну фирму. Фирма довольно долго думала и в результате выплюнула следующее:
"У нас командная работа (Scrum) и удалённая разработка из дома неприемлема. Только полный рабочий день и тесная работа в команде.

В остальном, кандидат конечно интересный."

Ай, как я люблю такие фирмочки. Сказать что над этим комментарием мы ржали в составе 35 человек из числа распределенной команды iDecide - ничего не сказать. Мы уже давно придерживаемся идеологически достаточно строгого agile и, хоть официально и не рекомендуется, работаем все удаленно (исключение составляет управление и маркетинг). И ничего, подчеркиваю, ничего не случилось плохого. Почему? Да потому что топы компании и среднее звено руководства - весьма и весьма грамотные люди, которые построили процесс, создали идеологию и (ВНЕЗАПНО!) все прекрасно работает и не разваливается.

Ребята, ну все же очевидно! Подобного рода утверждения обычно означают: "Нетнетнет! Нам нужен жесткий контроль над ВСЕМИ сотрудниками! Иначе никак!". Особенно прикрываться SCRUM-ом от удаленной работы - это как прикрываться веганством от жесткого, неистового секса. 

Потребность в строгом контроле и абсолютное неприятие удаленной работы свидетельствует только об одном - сюрприз-сюрприз - были прецеденты, когда без такого управления, команда шла вразнос, люди теряли фокус и тупо забивали на работу. Что, в свою очередь, недвусмысленно намекает что команда собрана из несамостоятельных и ленивых людей + руководство не знает что с ними делать. А тогда какой у вас, к херам собачьим, SCRUM?! Нет, это в лучшем случае корявый Waterfall. Потому что нельзя построить SCRUM на паноптикуме таких вот кадров. Ну не будет это работать - плавали уже, знаем. 

Тем не менее, представители надувают щеки и прикрываются умными словами. Господа, к чему надменность? Все мы вылезли из женской вагины. Вас никто не заставляет публично расписываться в своем (не)профессионализме (на минутку, что вы и делаете, говоря про SCRUM и удаленку в таком ключе). Можно просто сказать "мы не заинтересованы в удаленном сотрудничестве", или "сожалеем, но политика компании не подразумевает такого формата". Лучше честно сознаться что "не хотим, не будем", чем понапрасну умничать. Фу.

Тут можно было еще сказать что в нашем, академовском community любой мелкий аутсорсер, чуть только доросший до интегратора - мнит себя чуть ли не Газпромом и Microsoft-ом в одном лице. Но я не буду распинаться - это все итак понятно. Интересно только откуда эта надменность? Неужели НГУ так влияет?



воскресенье, 10 февраля 2013 г.

Extension-методы и разлом стереотипов

Сегодня сломались все мои представления о программировании на C# и extension-методах в частности, когда я увидел вот такой код:



1.Delay();
2.CreateThread();
3.WaitForUserInput();



А это оказались всего лишь extension-методы к int. Согласитесь, выглядит феерично.
Тут сразу же пришла на ум конструкция для более внятного кидания exception-ов:


"Access denied".InvalidOperation();
"File not found".FileAccess();
"Trying to instantiate incorrect type".FactoryError();
"Incorrect value: number expected".Validation<User>(u=>u.AgeString);

Полагаю, дальнейшие комментарии излишни.

вторник, 5 февраля 2013 г.

Совет про Dictionary


var d = new Dictionary<string,int>() {
    {"NumberOne" /* ключ */,1 /* значение */},
    {"NumberTwo",2},
    {"NumberThree",3},
};

Как ни странно, можно и так.

RavenDB Embeddable - коротко и по существу

Сессии:

  • Открытие сессии: дешевая, почти дармовая операция (65000 сессий за 300-500мс).
  • Закрытие сессии: и того дешевле (65000 сессий за 0-3мс)
  • По умолчанию количество запросов на сессию ограничивается 30 штуками. Устанавливается при в DocumentStore.Conventions.MaxNumberOfRequestsPerSession
Инициализация хранилища: 
  • очень дорогая операция - от 7с до минуты и больше
  • похоже, имеет место зависимость от размера хранилища
SaveChanges: 
  • дорогая операция. Зависит от количества объектов (1000 объектов за 1-15мс). 
  • В TransactionScope время выполнения не меняется.
Работа с Queryable: 
  • Выполненные Queryable кэшируются. После добавления данных нужно взять новый .Query<>
Работа с транзакциями: 
  • объекты оказываются в базе только после transaction.Complete(); или Dispose в using-блоке транзакции. Точно выяснить когда начинает работать .Count() после добавления объектов - не удалось
  • Уровни изоляции, судя по всему, не реализованы. 
  • Если SaveChanges прервертся во время выполнения без транзакции - умрет вся база! 


вторник, 29 января 2013 г.

Перемещение/resize окна в WPF

Проблема: хочу сделать окно со своим дизайном на WPF, но при убирании бордюра (NoBorder) оно перестает ресайзиться и двигаться за заголовок

Решение: Специально для этого в 7 и Vista есть библиотечка с пространством имен Microsoft.Windows.Shell, физически лежащим в PresentationFramework.dll. Там есть класс WindowChrome. Это лучше понимать как "хром окна", но по факту не только окна, но и любого элемента. Он содержит в себе набор attached-пропертей для манипулирования неклиентской областью окна. Пример:

<Style TargetType="{x:Type Window}">
        <Setter Property="shell:WindowChrome.WindowChrome">
            <Setter.Value>
                <shell:WindowChrome 
                                    CaptionHeight="24"
                                    CornerRadius="0"
                                    GlassFrameThickness="0,0,0,-1"
                                    NonClientFrameEdges="None"
                                    ResizeBorderThickness="7"
                                    UseAeroCaptionButtons="False"/>
            </Setter.Value>
        </Setter>
</Style>

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

shell:WindowChrome.IsHitTestVisibleInChrome="True"

А для ResizeGrip (или за что у вас там тянется, чтобы изменить размер окна):

shell:WindowChrome.ResizeGripDirection="BottomRight"

И все проблемы с перемещением окна будут решены.

четверг, 22 ноября 2012 г.

Проблема в wininet

Проблема: во время обращение к HTTPS-серверу через WinInet выясняется, что серверный сертификат отозван (ERROR_INTERNET_SEC_CERT_REV_FAILED)  или неверен (ERROR_INTERNET_INVALID_CA) или истек (ERROR_INTERNET_SEC_CERT_DATE_INVALID). Как правильно проигнорировать эти ошибки и продолжить обработку запроса?

Решение: необходимо отправить запрос, посмотреть GetLastError(), после чего поправить флаги соединения и отправить запрос еще раз. Видимо такая архитектура сделана для пущей безопасности, но это самая жуткий протокол взаимодействия подсистем, который я когда-либо видел. Флаги, которые нужно проставить для игнорирования ошибок:

  • ERROR_INTERNET_SEC_CERT_REV_FAILED - SECURITY_FLAG_IGNORE_REVOCATION
  • ERROR_INTERNET_INVALID_CA - SECURITY_FLAG_IGNORE_UNKNOWN_CA
  • ERROR_INTERNET_SEC_CERT_DATE_INVALID - SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
Код:

BOOL bRepeat = FALSE;
int sendResult = 0;
do{
bRepeat = FALSE;
sendResult =  HttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);
if (!sendResult){
int lastErr = GetLastError();
if (lastErr == ERROR_INTERNET_INVALID_CA) {
WARNING("Серверный сертификат недействителен");
DWORD dwFlags;
DWORD dwBuffLen = sizeof(dwFlags);
InternetQueryOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS,(LPVOID)&dwFlags, &dwBuffLen);
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
InternetSetOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
bRepeat = TRUE;
}else if (lastErr==ERROR_INTERNET_SEC_CERT_REV_FAILED){
WARNING("Серверный сертификат отозван");
// аналогично SECURITY_FLAG_IGNORE_REVOCATION
bRepeat = TRUE;
}else if (lastErr==ERROR_INTERNET_SEC_CERT_DATE_INVALID){
WARNING("Серверный сертификат ИСТЕК");
// аналогично SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
bRepeat = TRUE;
}else{
MLASTERROR
ERROR("Не удалось отправить веб-запрос");
}
}
}while(bRepeat);
return sendResult;




Проблема в C++ со строками

Проблема: не могу понять в чем разница между BSTR, LPSTR, LPWSTR, LPTSTR и прочими строками в С++.

Решение:

  • CHAR - это typedef на char - обычный байт от 0 до 255 или от -128 до +128
  • WCHAR - это typedef на wchar_t - "широкий" символ, которого по стандарту должно быть гарантировано достаточно для хранения любой буквы любого алфавита. На практике это не так, ибо в GNU-шных компиляторах вместимость wchar_t - 32 бита (4 байта). В ms-компиляторах - 16 бит, чего уж точно не хватает на все алфавиты, поэтому используются свои извращения. Важно понимать что WCHAR - это не тот же самый Unicode
  • TCHAR - если при сборке задан #define UNICODE, то будет преобразован в WCHAR, если нет - то в CHAR. #define UNICODE по факту вносит путаницу, ибо как было сказано - wchar_t - не является юникодом. При использовании TCHAR - все системные вызовы так же перейдут на широкие символы если будет задан #define UNICODE. Для того, чтобы и c-style функции перешли на широкие символы - необходимо использовать те, что с префиксом _tcs (_tcslen, _tcscat, _stprintf). std-контейнеры не переходят на широкие символы автоматически. Однако это легко решается методами вроде: 
#ifdef UNICODE
#define std::string std::wstring
#endif
  • Постфикс STR - признак массива CHAR/TCHAR/WCHAR-ов. Сам по себе не используется
  • Префиксы LP, P - признак указателя на массив CHAR/TCHAR/WCHAR-ов, в зависимости от названия (например, LPWSTR - указатель на массив WCHAR-ов, LPTSTR - TCHAR-ов, LPSTR - просто CHAR-ов). LP - "длинный" указатель (Long Pointer), не знаю что значит. P - обычный указатель (Pointer)
  • BSTR - по факту всегда является LPWSTR. Используется для общения с COM-интерфейсами и только с ними. Потому как там все только на широких строках. Для операции с ним есть ATL-класс CComBSTR, предоставляющий инструменты конвертации. Так же стоит иметь в виду вызовы ::SysAllocString и ::SysFreeString.
Раздел MSDN, который поможет не умереть с тоски: Unicode and Character Set Functions (Windows)

Совет

Отправляешь e-mail из программы? От греха по-дальше - не именуй аттачи русскими буквами. Не любит этого SMTP.