Сегодня второй день в должности дизайнера. Собственно, что я выяснил:
"Дизайн - это вам не программинг, тут головой думать надо!"
Пока все.
Powered by .NET :)
Сегодня второй день в должности дизайнера. Собственно, что я выяснил:
"Дизайн - это вам не программинг, тут головой думать надо!"
Пока все.
Оригинал здесь.
До 2002 года я открыто отвергал большинство IDE. Они казались мне слишком настойчивыми. Они постоянно пытались контролировать мою систему сборки или формат кода. Если я хочу раскрыть какие-то вещи, мне нужно что-то взамен. Долгое время обмен не казался мне честным. THINK C на Macintosh был единственной IDE, которая действительно мне нравилась.
Visual Studio .NET 2002 стала первой IDE для Windows, расположившей меня в себе. Я до сих пор использую vi или emacs почти каждый день, но допускаю, что стал больше использовать Visual Studio.
В прошлом году я перешел на Visual Studio 2005 и полюбил ее. Это настолько великолепный продукт, что меня беспокоило, каков же будет следующий релиз. И вот вышла Visual Studio 2008, вероятно, вскоре я попробую ее. Но Visual Studio 2005 похожа на "Если оно работает, так и нечего беспокоиться". Последнее, что мне нужно, это чтобы она стала в чем-то хуже, потому как я совершенно не представляю, как она могла бы быть лучше.
Я догадываюсь, когда что-то уже появляется в IDE, просто у меня не очень хорошее воображение. :-)
Я начал использовать Eclipse несколько недель назад и теперь понимаю, где Visual Studio находит пространство для улучшений. Я думаю, Eclipse удивительна, и я лишь прошелся по поверхности.
Во всяком случае, вот пара избранных мной на этот раз фич Eclipse:
Когда я установил Eclipse, первое, что я сделал - поискал пункт меню для начала сборки приложения. Когда я не нашел ни одного, я предположил, что должно быть, система меню здесь в полном беспорядке и контринтуитивна. Как они допустили, что такую часто используемую команду так сложно найти?
Конечно, теперь я понимаю, что Eclipse не имеет такой команды, потому как сборка выполняется автоматически и постоянно. В действительности, такая возможность меня зацепила. Однажды это привело в замешательство, однако в остальном оно Просто Работает. Я делаю изменения в коде, сохраняю файл и панель Problems автоматически показывает существующие предупреждения и ошибки. Приятно.
В действительности, этим утром я потревожил Visual Studio 2005 чтобы исправить баг. После внесения изменений, я сохранил файл и уставился вниз экрана в ожидании запуска компиляции. Лишь несколько секунд спустя я догадался нажать Ctrl-Shift-B.
Мне действительно по душе функция Quick Fix в Eclipse. В основном, всякий раз, получая ошибку компиляции или предупреждение, я ставлю текстовый курсор на "проблемное" место и жму Ctrl-1. Это вызывает инструмент Quick Fix, который отображает окно со списком путей решения данной проблемы. Например, если я пытаюсь вызвать несуществующий метод, мне предлагается создать его.
Студия предлагает сходные возможности (например, Generate Method Stub), но Quick Fix кажется более оригинальным. Мне почти всегда предлагается несколько вариантов разрешения ситуации, включая предпросмотр результата быстрой правки.
Это особенно удобно, если имеешь дело с исключениями. Я большей частью испытываю неприязнь к тому, что Java заставляет объявлять, какие исключения могут быть брошены из метода. Ctrl-1 дает мне также возможность с легкостью добавить объявления типов исключений или блоки try/catch.
Ясно, что я новичок в Eclipse, так что мои представления о ее возможностях могут быть неверными. И как я и сказал, я лишь начинаю. Во время написания данного поста я обнаружил "Generate Constructor Using Fields...". Жаль, что я нашел это немного раньше. :-)
В любом случае, вы можете свободно меня корректировать, дополнять или обвинять в невежестве или называть 7 причин, по которым я должен использовать IntelliJ.
Но главным образом я лишь говорю, что опыт с Eclipse дал мне намного большие перспективы по части IDE в общем. Сравнивая Visual Studio и Eclipse, я не могу назвать, который из них однозначно лучше. По большей части я впечатлен, что эти два соперника могут научиться так многому друг у друга.
Продолжим тему миграции. Перевод первой части пресдтавлен здесь, а ниже представлен перевод части 2. А в это время у Эрика уже имеется часть 4.
Как я уже упоминал в части 1, прошло уже прочти десять лет с тех пор, как я последний раз писал на Java. Очевидно, что этого достаточно, чтобы подавить некоторые наиболее неприятные воспоминания. Например, я совсем забыл, как работает следующий код:
String a = new String("foo");
String b = new String("foo");
if (a == b)
{ // этого никогда не случится
}
В C# используя оператор == вы получаете ожидаемое. В Java == значит лишь, что две строки представляют собой один обхъект, а не равенство самих строк.
Более широко, возарвщение к Java заставляет меня понять, насколько я разбираюсь в перегрузке операторов в C#.
Я не говорю, что считаю перегрузку операторов действительно полезной для моих собственных классов. Главным образом, я считаю это лишь способом позволить программистам создавать плохой код. Я допущу использование перегрузки операторов в малых долях в Sawdust для упрощения манипуляций с 3D точками и векторами, но я мог-бы обойтись и без них.
Те мне менее, мне действительно нравится использование перегрузки операторов в классах .NET Framework:
Ничего из этого не доступно в Java, и я теряю их всех.
Особенно это касается строк.
Однако это еще не так огорчает.
Что действительно шокирует, так это то, что постратил неделю или около того на написание неверного кода и не получил никаких предупреждений от среды разработки. Я не понимал, что == не может быть использован для сравнения строк, пока не обратил внимание на некорректные результаты, выдаваемые приложением, и не начал раскапывать причины. Думаю, какое-нибудь предупреждение на этот случай было бы к месту.
И откровенно я был сильно удивился, когда не получил ни одного. Я считаю верно - такое ощущение, что Eclipse делает удивительную работу по части отслеживания ошибок и предупореждений.
Серьезно, Eclipse самая болтливая среда разработки что я использовал, и нет, я не жалуюсь. Я нахожу Eclipse чрезвычайно приятным. Он придупреждает иеня о многом, но эти предупреждения непосредственны, уместны и полезны.
И поэтому я немогу поверить, что никакая часть среды Eclipse не решилась предупредить меня о сравнении строк. Мои ожидания были очень высоки. Eclipse предупреждает меня так часто, что я даже заметил, что пытаюсь сидеть в правильной позе, лишь бы не обратить на это его внимание. Но по некоторым причинам, Eclipse молча принял использование == для сравнения строк, даже если такое использование в большинстве случаев некорректно.
Думаю, я только здесь закончил свои жалобы.
Я сожадею, что этот пост в целом позитивен к C# и негативен к Java. Чтобы удержать баланс, в части 3 я остановлюсь на некоторых областях, где Eclipse выглядит лучше, чем Visual Studio. Way better. :-)
Я и сам хотел написать несколько постов на тему перехода из .NET на Java, но, не дочитав до конца спецификацию Java, заявлять о чем-то не решался.
Вообще, эта тема мало рассмотрена. Об обратном переходе говорится везде, и книги тоже выходят. А здесь такие вот пробелы.
По теме нашел лишь следующее:
А тут вот Эрик Синк представил серию постов (пока 3 штуки) на эту тему. Ниже представлен перевод части первой.
Пару недель назад я начал еше один проект. Мои регулярные читатели, знают, что в основном я использую C#. Тем не менее, для этого проекта я решил воспользоваться Java и Eclipse.
Я не писал на Java уже несколько лет. Версия JDK в то время была 1.1.7. Средой разработки была Symantec Café, Supercede и Emacs. Понятие рефакторинг значило не более чем тема диссертации Билла Оупдайка (файл PostScript). Eclipse появилась несколькими годами позже.
Я думаю, настало время освежить свои взгляды.
Моя младшая дочь спит. Время от времени она встает посреди ночи и начинает ходить во сне. Я найду ее внизу в семейной комнате бормочащей о животных в зоопарке. Я возвращаю ее назад в кровать. А с утра она уже ничего не помнит. Почему она делает это? Я не знаю, но предполагаю, что у любого будут проблемы со сном после двухчасового просмотра The Suite Life of Zach and Cody.
Или, возможно, это наследственное. Видимо, на прошлой неделе я встал посреди ночи, поехал к O'Hare, полетел в Сан-Хосе, взял такси в штаб-квартиру Sun, наплевал на их газон, поехал домой и вернулся в кровать.Я не помню ничего из этого.
Что я помню, так это то, на что я обратил внимания в Java - что фигурные скобки располагаются на предыдущей строке, и мое умственное здоровье стало стремительно ухудшаться.
Мне заметно полегчало, когда я открыл диалог настроек Eclipse и сделал следующее:
Ах да, и это тоже:
Эти изменения настроек возымели для меня огромное значение. По-видимому, естественный стиль в мире Java - располагать фигурные скобки на одной строке с предшествующей ей конструкцией. Но в любом случае я не смог бы к этому привыкнуть. я не говорю, что мой стиль объективно лучше. Я лишь говорю, что не могу справиться.
К счастью, Eclipse обладает невероятными функциами кастомизации. После вышеизложенных изменений я лишь нажал "Ctrl-Shift-F" и весь мой код стал намного привлекательней для меня.
Я надеался, что это работало и за пределами IDE. Я приобрел Head First Java и Java in a Nutshell. Обе книги были великолепны, но я продолжал обнаруживать свою левую руку жмущей "Ctrl-Shift-F" в надежде отворматировать книжную страницу.
Этим утром по пути на работу я заметил чью-то попытку свернуть с неверной полосы. Моя левая рука жала "Ctrl-Shift-F".
Замечательная кастомизируемость Eclipse пришла на выручку снова для раскладок клавиш. Разница между Visual Studio и Eclipse значительна.
Например, три наиболее часто используемые мной команды отладчика: Debug, Step Over, и Step Into.
Правда в том, что я ищу раскладку Visual Studio и могу набрать указанное выше. Сознательно я не знаю, что они значат. Они лишь запрятаны где-то в моей бессознательной памяти. Это автоматизм. И когда я впервые запустил отладку в Eclipse, кое-что работало совсем не так хорошо.
В действительности, комбинации клавиш настолько различны по сравнению с Visual Studio, что я заподозрил их умышленное происхождение из недоброжелательных причин. Тем не менее, пока я не нашел сочетание клавиш, означающих "Go to Declaration" в одной среде и "Reformat my Hard Disk" в другой, я собирался отложить все подозрения и принять свою излишнюю параноидальность.
До сих пор я делаю знать, что значит "Ctrl-Shift-F" в Visual Studio?
Обычно я не люблю делать излишнюю кастомизацию своей рабочей среды. В конце концоа, я пользователь Windows. Все мои измененные настройки теряются после переустановки системы. Легче научиться пользоваться вещами в из естественном состоянии.
Но если я собираюсь использовать Visual Studio и Eclipse одновременно, мне определенно нужно, чтобы один из них был немного сходен с другим.
Часто возникает необходимость в небольшом сайте, но ASP.NET оказывается слишком тяжеловесен, статичный HTML не устраивает совмещением данных и представления, а PHP или SSI просто брезгуешь.
В случае же использования XSLT кодирование займет ненамного больше времени, чем в случае с HTML. В этом посте я рассмотрю 2 варианта развертывания XSLT-сайта под ASP.NET.
Трансформацию на стороне клиента не рассматриваю, потому как на любителя это. Не в том смысле, что простые пути - не наш выбор, а в том, что выставлять данные напоказ... хмм... нет.
Пример:
/test1/default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> // <root title="Page Title"> <data> <item text="node 1 contents" /> <item text="node 2 contents" /> <item text="node 3 contents" /> </data> </root>
/test1/default.aspx.cs:
public partial class _Default : XslTransformPage { public _Default() : base("test1.xsl") { } }
Как видно, содержимое страницы представляет собой данные в формате XML. И страница эта наследуется от XslTransformPage, реализующего функционал XSL преобразования:
/app_code/xsltransformpage.cs:
using System; using System.IO; using System.Text; using System.Xml; using System.Xml.Xsl; using System.Web; using System.Web.Caching; using System.Web.UI; // public class XslTransformPage : Page { public XslTransformPage() { } // public XslTransformPage(string styleSheetFile) { this.styleSheetFile = styleSheetFile; } // private string styleSheetFile; public string StyleSheetFile { get { return styleSheetFile; } set { styleSheetFile = value; } } // protected override void Render(HtmlTextWriter writer) { if (Cache[Request.RawUrl] != null) { writer.Write(Cache[Request.RawUrl].ToString()); return; } // string xslPath = Server.MapPath("~/App_Code/" + styleSheetFile); if (!File.Exists(xslPath)) throw new HttpException(404, "Cannot find " + Request.RawUrl); // XslCompiledTransform transform = new XslCompiledTransform(); transform.Load(xslPath); // StringBuilder inBuilder = new StringBuilder(); StringBuilder outBuilder = new StringBuilder(); // using (StringWriter sw = new StringWriter(inBuilder)) using (HtmlTextWriter hw = new HtmlTextWriter(sw)) { //Получает содержимое страницы, т.е. данные в xml base.Render(hw); // using (StringReader sr = new StringReader(inBuilder.ToString())) using (XmlReader xr = XmlReader.Create(sr)) // using (XmlWriter xw = XmlWriter.Create(outBuilder)) transform.Transform(xr, xw); } // Cache.Add(Request.RawUrl, outBuilder.ToString(), new CacheDependency(new string[] { Request.PhysicalPath, xslPath }), Cache.NoAbsoluteExpiration, new TimeSpan(24, 0, 0), CacheItemPriority.Normal, null); // writer.Write(outBuilder.ToString()); } }
Кроме преобразования здесь используется также кеширование результата преобразования.
Как, наверное, понятно, используется HttpHandler, навешиваемый на расширение .aspx, вот таким образом:
app.config:
<httpHandlers> <add verb="*" path="*.aspx" type="XslTransformHandler"/> </httpHandlers>
Теперь сам обработчик:
/app_code/xsltransformhandler.cs:
using System; using System.IO; using System.Text; using System.Web; using System.Web.Caching; using System.Xml; using System.Xml.Xsl; // public class XslTransformHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { string path = context.Request.Path.Substring(context.Request.ApplicationPath.Length); // ProcessRequest(context, path); } // public void ProcessRequest(HttpContext context, string path) { context.Response.ContentType = "text/html"; // if (context.Cache[path] == null) { string xslPath = String.Empty; string xmlPath = String.Empty; // string xslFile = String.Empty; string xmlFile = String.Empty; string xmlDir = String.Empty; // string[] parts = path.Contains("/") ? path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries) : new string[] { path }; // // Замечу, что файл стилей будет один для каждой папки, для корневой: // default.xsl, ... if (parts.Length == 1) { xslFile = "default.xsl"; xmlFile = Path.GetFileNameWithoutExtension(parts[0]) + ".xml"; xmlDir = ""; } // ... для вложенных - вида папка.папка...папка.xsl else { xslFile = String.Join(".", parts, 0, parts.Length - 1) + ".xsl"; xmlFile = Path.GetFileNameWithoutExtension(parts[parts.Length - 1]) + ".xml"; xmlDir = String.Join("/", parts, 0, parts.Length - 1); if (xmlDir.Length > 0) xmlDir += "/"; } // xslPath = context.Server.MapPath("~/App_Code/" + xslFile); xmlPath = context.Server.MapPath("~/App_Data/" + xmlDir + xmlFile); // if (!File.Exists(xmlPath) || !File.Exists(xslPath)) throw new HttpException(404, "Cannot find" + context.Request.RawUrl); // XslCompiledTransform transform = new XslCompiledTransform(); transform.Load(xslPath); // StringBuilder sb = new StringBuilder(); using (XmlReader xr = XmlReader.Create(xmlPath)) using (XmlWriter xw = XmlWriter.Create(sb)) transform.Transform(xr, xw); // context.Cache.Add(path, sb.ToString(), new CacheDependency(new string[] { xmlPath, xslPath }), Cache.NoAbsoluteExpiration, new TimeSpan(12, 0, 0), CacheItemPriority.Normal, null); // context.Response.Write(sb.ToString()); } else context.Response.Write(context.Cache[path].ToString()); } // public bool IsReusable { get { return false; } } }
Пример:
Для запрашиваемого /test2/default.aspx данные будут распологаться в /App_Data/test2/default.xml, а стили в /App_Code/test2.xsl
Для запрашиваемого /test2/subdir/page.aspx: в /App_Data/test2/subdir/page.xml и /App_Code/test2.subdir.xsl соответственно.
А самого файла .aspx может и не существовать, либо в случае со страницами по умолчанию (например, default.aspx) он может присутствовать и быть пустым, чтобы IIS был в курсе о ее существовании.
Также, как и в случае со статичными данными, xml может быть получен и из БД (SELECT FOR XML) и вообще откуда угодно, и оба описанных метода можно приспособить в том числе и для этого.
Да, немногословно как-то получилось :)
Задание версии и даты сборки при компиляции
Недавно около часа гуглил как же запихнуть в AssemblyInfo ревизию SVN. Остановился было на сборнике MSBuild тасков, когда обнаружил замечательную утилиту SubWCRev из состава Tortoise SVN, которая вдобавок умеет вставлять еще и дату.
Используется это так:
[assembly: AssemblyDescription("Inductive UI Toolkit Test Application. Built at $WCDATE$.")] |
<Import Project="$(MSBuildProjectDirectory)\..\RevisionInfo.targets" /> |
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
В IuiToolkit встала необходимость заиметь такое свойство, которому уже в дизайнере можно было бы присвоить следующие значения:
public class TasksEditor : UITypeEditor |