Вассерман
Некто Анат. Вассерман излагает свои соображения относительно Чернобыля: http://awas.ws/HOBBY/TECHNICS/CHERNBYL.HTM
Некто Анат. Вассерман излагает свои соображения относительно Чернобыля: http://awas.ws/HOBBY/TECHNICS/CHERNBYL.HTM
Отправил
Das Ich
в
2:18 AM
0
раз прокомментировано
Какая разница и не наплевать ли? Нет. Не наплевать. Минута разговора мне теперь обходится в $35. Уже устал общаться финотделом и возвращать свои деньги. Обидно было бы сменить оператора, которым пользовался 5 лет.
Отправил
Das Ich
в
4:30 AM
0
раз прокомментировано
Сегодня (вчера уже) после банки пива мне пришло в голову, что человек произошёл от трансформатора. Когда подопьёт - начинает гудеть.
Отправил
Das Ich
в
3:14 AM
0
раз прокомментировано
Ещё один день закончился (как раз в то время, как у других он только начинается). Закончился он написанием шаблонов для двухступенчатых преобразований текстов. В общем и целом - ничего особенного. Однако для ряда случаев - очень полезна. Таковых случаев я знаю несколько, но все они сводятся к применению т.н. skins. В некотором смысле - высшая форма отделения представления от "логики". Говоря честно, мне по-английски такие тексты было бы писать проще, а то все эти кавычки... Ну так вот. Суть можно изложить в трёх предложениях:
1. Объект, моделирующий нечто, отдаёт свои данные в виде XML
2. По строке (а ведь всякий XML - строка, чем и ценится) строится метамодель представления (тоже в XML) путём применения к исходному XML XSLT
3. К метамодели применяется другой XSLT (а может, третий, четвёртый и т.п.), отвечающий за применение к метамодели skins.
В итоге получаем HTML, который:
а) на лету подстраивается под любого пользователя
б) позволяет радикально сократить число классов-представлений для отображения данных
Вкратце, механизм (С#, .NET 1.1)...
1. Класс, ответственный за что-то, должен уметь представить свои данные в XML
class BusinessClass{
int m_Id = 123;
string m_Name = "Name";
...
public string ToXml()
{
string s = "";
s += "<downloadupdate>";
s += "<id>";
s += m_Id.ToString();
s += "</id>";
s += String.Format("<name>{0}</name>", m_Name);
s += "</downloadupdate>";
return s;
}
}
2. Написать XSLT, который по XML-данным объекта формирует метамодель. То есть, например
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" indent="yes"/>
<xsl:template match="downloadUpdate">
<line><xsl:apply-templates/></line>
</xsl:template>
<xsl:template match="downloadUpdate/id">
<cell><xsl:apply-templates/></cell>
</xsl:template>
<xsl:template match="downloadUpdate/name">
<cell><xsl:apply-templates/></cell>
</xsl:template>
</xsl:stylesheet>
3. Написать ещё один XSLT, который применял бы к метамодели skin.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" indent="yes"/>
<xsl:template match="line">
<HTML>
<BODY>
<TABLE>
<TBODY>
<TR>
<xsl:apply-templates/>
</TR>
</TBODY>
</TABLE>
</BODY>
</HTML>
</xsl:template>
<xsl:template match="cell">
<TD>
<xsl:apply-templates/>
</TD>
</xsl:template>
</xsl:stylesheet>
4. Это почти всё. Трансформации, КГБычно, выполняются примерно так.
Это первый шаг преобразования, после него получаем что-то вроде
XmlDocument doc = new XmlDocument();
doc.LoadXml(object.ToXml());
XPathNavigator nav = doc.DocumentElemen.CreateNavigator();
MemoryStream ms = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8);
XslTransform xt = new XslTransform();
xt.Load(PATH_TO_XSLT_1);
xt.Transform(nav, null, writer, null);
ms.Seek(0, SeekOrigin.Begin);
byte[] b = new byte[ms.Length];
ms.Read(b, 0, (int)ms.Length);
ms.SetLength(0);
string s = Encoding.UTF8.GetString(b);
<?xml version="1.0" encoding="utf-8"?>
<line>
<cell>123</cell>
<cell>Name</cell>
</line>
На втором шаге надо к строке s применить то же самое, что и к исходному XML, а потом выбросить результат в Response. Из побочных эхвектов я отмечаю большую нагрузку на процессор, что надо иметь в виду.
Может, как-нибудь напишу, как генерацию представления правильно совместить с серверными элементами управления. Но уж не сегодня.
Отправил
Das Ich
в
4:20 AM
0
раз прокомментировано
Бывает так, что надо запретить доступ только к некоторым страницам web-приложения. Чтобы не городить собственных безумств, надо пользоваться механизмом, уже существующим в .NET. Наиболее простой из них - Forms Auth.
Схема его работы проста:
1. В web.config указываются защищаемые страницы
2. Там же указывается, куда надо направить пользователя при попытке пробраться к данным, требующим авторизации
3. На странице проверки полномочий юзверя (п.2) выполняем проверку (можно стандартными средствами, через записи в web.config, а лучше - через БД) и если всё нормально - пользователь идёт на ту страницу, куда его с ходу не пустили.
Вроде ничего особенного, но.
1. Не нужно изобретать механизма. Обычно лепят что-то через cookie, session и пр. Это ужасно.
2. Это точно работает и гибко, при томЪ.
В деталях это выглядит так.
1. В web.config вносим запись
<configuration>
<location path="download.aspx">
<system.web>
<authorization>
<deny users="?">
</deny>
</authorization>
</system.web>
</location>
<configuration>
<system.web>
<authentication mode="Forms">
<forms loginurl="login.aspx"/>
</authentication>
</system.web>
static object m_RedirectSync = new object();
public static void Redirect(Page Current, string Url)
{
lock(m_RedirectSync)
{
Current.Response.Buffer = true;
Current.Response.Status = "302 Moved Temporarily";
Current.Response.AddHeader("Location", Url);
Current.Response.AddHeader("Content-Length", "0");
Current.Response.Flush();
}
}
Отправил
Das Ich
в
4:57 AM
0
раз прокомментировано
Вчера ни с того, ни с сего дико заболел. Проспал сутки. А сегодня весь день потратил на переделку (а фактически - на написание с нуля) сайта. Горло болит.
Отправил
Das Ich
в
1:04 AM
0
раз прокомментировано
Вчера днём я получил наконец-то код нашего сайта и всё не доходили сутки руки его посмотреть более пристально. Но вот дошли и лучше бы я туда не заглядывал. Я хочу убить человека, который это делал. Чудовищная смесь технической безграмотности, лени, неумения, наплевательства на всё и всех, помноженные на ложь - своё дело сделали.
Код не просто нерабочий. Это просто мешанина какая. Имена переменных вроде
f_Id, mX
классов _default, db, ThisIsMyFirstMeaningFullClass.
Отправил
Das Ich
в
4:06 PM
2
раз прокомментировано
Сколько раз уже говорили людям: "используйте правильные имена для переменных, свойств и методов". Кивают головой, соглашаются и делают наоборот. А вот очень просто. Получаю от тестировщика: "Smoke test failed". Ну и причины там... Суть такая, что в процессе работы происходит обращение к неразмещённому объекту. Что-то вроде:
si.Subject.LastName = someName;
при этом свойство Subject получается следующим образом:
public Subject Subject
{
get
{
if (m_Subject == null)
{
if (!IsNew && SubjectId > 0)
{
SubjectsEngine eng = new SubjectsEngine();
m_Subject = eng.GetSelected(SubjectId)[0];
}
else if (ShouldCreateStub)
m_Subject = new Subject();
}
return m_Subject;
}
set
{
SubjectId = value.Id;
m_Subject = value;
}
}
Ничего особенного? Так и есть. Но представьте себе, что ShouldCreateStub
называется не так, как оно тут называется, а, положим, MustIgnoreEmptiness
и определено так:
private bool m_OldBehavior = true;
public bool MustIgnoreEmptiness
{
get {return m_OldBehavior;}
set {m_OldBehavior = value;}
}
? Как тут можно вообще понять, что имел в виду автор? Для чего он эдак накрутил? Я не знаю, а вот время потратил. И ведь styleguide есть...
Отправил
Das Ich
в
9:16 PM
0
раз прокомментировано
Мы готовимся подавать документы на партнёрство с Microsoft. Для этого нужно иметь в штате двоих сертифицированных людей и три ссылки на успешный опыт внедрения. НачинаемЪ.
Отправил
Das Ich
в
11:30 PM
0
раз прокомментировано
Потратил несколько часов на решение проблемы, возникшей на ровном месте. А именно. Есть код типа следующего:
Type type = null;
foreach(Assembly next in AppDomain.CurrentDomain.GetAssemblies())
{
// здесь какие-то проверки, результатом которых является
// заполнение переменной type
}
object obj = Activator.CreateInstance(type);
BaseType bt = (BaseType)obj; // *
// * - надо заявить, что Type является потомком BaseType
И вот, при выполнении // * происходит забавная вещь: исключение "Specified cast is not valid." Забавность этой вещи заключается в том, что возникает это исключение только при выполнении "большого проекта", в случае теста ошибка не воспроизводится. Причины мне до сих пор неизвестны, хотя есть подозрения, что происходит обращение к разным версиям сборки. Чтобы обойтись без приведения, пришлось использовать reflection, который оказался как раз к месту:
object sp = Activator.CreateInstance(type);
type.InvokeMember("LoadConfig", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public, null, sp, null);
Исследования продолжаются. Система сообщения об ошибках, имеющаяся в .NET 1.1 является одной из самых бессмысленных из всех, что я только видел. Это очевиднейший пережиток "времён позднего DCOM", тратить время на борьбу с которым лично мне - жалко.
Отправил
Das Ich
в
11:46 PM
0
раз прокомментировано
Сегодня днём мы будем пытаться выцарапать свои деньги. Надеюсь, что всё получится, потому что у нас масса планов и идей и не хотелось бы, чтобы какие-то уроды помешали в их воплощении. Но это всё будет позже, а пока мы пересылаем друг другу письма, в которых оттачиваем формулировки и аргументацию, которые должны подействовать. Вместо полезной работы.
Завтра, кстати говоря, начинается 3 (2-то уж точно) больших дела.
1. Наш инженер-теплотехник, которого я привлёк к работе в последнюю свою поездку в Псков, предоставил уже достаточно информации для того, чтобы можно было начать работу над расчётной моделью тепловых потерь и теплогидравлического состояния системы. Сколько при этом придётся сделать - я себе уже примерно представляю. Это должна быть интересная работа, поскольку расчёты будут выполняться не так, как в первой версии (комом), а на основе взаимодействия нескольких веб-сервисов. Клиентов не поймёшь: одни не любят WinForms-приложения, других воротит от "Web-примитива", а с WS это уже не играет никакой роли.
2. Пилотный проект системы мониторинга для нашего заказчика-кидальщика на основе рабочих мест-КПК. А то "эффект бомбы", "эффект бомбы"... Вот и посмотрим, что это за эффект такой. У меня уже сколько зря простаивает на столе этот iPAQ (QAPi) - музыку слушаю, когда не за компьютером да почту проверяю (вчера вечером в Шоколаднице на Софийке всё проклял, пока подключился к серверу - там у оператора какие-то проблемы с покрытием...). Забавно, кстати, на КПК расшифровывать письма через консоль и gpg. Минуту-другую-то у меня точно занимает. Но я отвлёкся. Эта система в идеале позволит нам выпустить в город злых людей в форме, обуздав при этом их жажду крови: они будут рвать только на основании огонька. Пока красный не загорится - они не должны будут и близко "принимать меры". Всё это в целом позволит гражданам вздохнуть свободнее и спокойнее. Да и люди в форме, может (можыд? мойшет?) быть, тоже одумаются.
3. Дневник программиста, видимо, станет таковым. Сейчас, например, меня интересуют реализации WS-Reliable, WS-Addressing и WS-Secure на платформах .NET 1.1 и .NET 2.0. В сравнении с тем, что есть для Java. А то я давно уже слышу, как это прекрасно - жить в Java, но что-то не очень верится. Посмотрим. И тут расскажу.
UPDATE
Встреча п.1 перенеслась. Жаль.
Отправил
Das Ich
в
1:57 AM
0
раз прокомментировано
Работа без договора- сущее наказание. В процессе сдачи проекта выяснилось, что заказчик отказывается доплатить нам $40'000 разницы между полной суммой работ и выплаченной частью. Как теперь разговаривать, какие аргументы использовать, если на той стороне просто не хотят платить? Всё усугубляется ещё и тем, что в команде не все верят в то, что нас пытаются кинуть. Я говорю: прекращаем всю работу над этим проектом до прояснения ситуации, а мне отвечают: "я не согласен. 2 дня до дня переговоров нам не делают погоды". С момента первого звонка - 10 августа -прошло 2 месяца, больше, и всё это время мы работали, исходя из этого дурацкого принципа: "ну ещё 2 дня ничего не решают".
Как бы не так! Решают. И ещё как! Теперь надо за 12 часов изменить стратегию работы, переоткрыть наши прочие направления и забыть уже не только про выходные, но и про "выспаться".
Отправил
Das Ich
в
2:33 PM
0
раз прокомментировано
Сегодня и завтра я работаю без тестировщика. Непривычно выпускать версию, писать на проект, что версия готова и не получать отклика от тестировщика. Чтобы времени не терять, я решил в FogBugz пройтись по инцидентам, что ещё не закрыты. Закрыта проблема с интерфейсом для поиска повторений в объектах, сомнительная ошибка с ключами, которые якобы не должны генерироваться, если не указан email отправителя... Дурацкий какой-то день, бестолковый.
Отправил
Das Ich
в
7:05 PM
0
раз прокомментировано