Wednesday, August 20, 2014

Мой обзор читалки Kindle Paperwhite

В этой статье постараюсь сделать небольшой обзор читалки, которую приобрел на амазоне (Kindle Paperwhite), с ее положительными и отрицательными сторонами. Начну с небольшого отступления о покупках на Amazon. На амазоне я начал приобретать разные товары, начиная с книг по разработке и заканчивая разными электронными устройствами, около полугода назад. Поскольку в основном там можно купить довольно дешево бумажную техническую литературу в оригинале, я сделал несколько заказов на амазоне, и мне понравился их сервис. С доставкой за все время не возникло никаких особых проблем. Разве что неприятная и досадная мелочь: для нерезидентов США у них нет скидок. Я покупал, когда на ридер порядком упали цены, но поскольку не проживаю в США, на меня эти расценки не распространялись, и в итоге заплатил на парочку долларов дороже.  
О данной читалке уже есть несколько отзывов на хабрахабр: "Обзор Kindle Paperwhite 2013: чем второе поколение лучше" и "Обзор нового Kindle Paperwhite (2013)". Но лучше всего, пожалуй, обзор данной читалки сделал Скотт Хансельман: "Amazon Kindle Paperwhite 3G/Wi-Fi Review". Тольку у Скотта немного круче читалка, чем у меня, благодаря поддержке 3G, которая мне, в принципе, не была нужна, поэтому выбор был остановлен на читалке подешевле. 
Остановлюсь на негативных впечатлениях о данной читалке, так как позитивных вы увидите очень много, и большинство из них действительно правда.
У данной читалки очень впечатляющие характеристики:
За исключением такого малого количества поддерживаемых форматов. Экран данной модели 6 дюймов. С данной читалкой есть небольшая проблема. На ней очень четко видны следы пальцев на задней крышке, вокруг дисплея. Поэтому рекомендуется купить также чехол для читалки. 
Ниже добавлю пару фоток, чтобы показать, как это выглядит на самом деле. (Такой же чехол у Скотта Хансельмана, ссылка на обзор которого приведена выше).
Чего не занимать этому ридеру, так это великолепной подсветки. В нем прекрасно настраиваемый режим подсветки, который позволяет читать ваши книги так, словно вы читаете настоящую книгу.
Настраивается режим очень легко, как показано на рисунке ниже.
Первым делом после покупки данной читалки на амазоне нужно ее сразу зарегистрировать, чтобы иметь возможность скачивать книги с сайта, и, по сути, указать, кому принадлежит данная читалка. Некоторые пользователи пишут, что в амазоновских ридерах много рекламы. Это все ерунда. Почти за три месяца пользования я не заметил там такой назойливой рекламы, о которой пестрят рассказы о данной читалке. Она есть при просмотре книг на амазоне через браузер, который встроен в читалку. Но она настолько незаметна, что я не вижу в этом каких-либо проблем.  
Один из огромных плюсов данной читалки  это два встроенных словаря для перевода слов на английский язык. Незнакомые слова в процессе чтения можно сразу посмотреть в словаре.
Также для меня огромное значение имеет в данном ридере возможность делать заметки, и удобный поиск по самим заметкам. Так как я в последнее время веду технический блог, и часто возникает потребность ссылаться либо анализировать какую-то книгу, ее плюсы и минусы, то очень сложно вспомнить спустя некоторое время то, чем бы хотел поделится с читателями. Благодаря заметкам можно выделить интересную, яркую мысль и сохранить на ридере, а затем перечитать в нужный момент эти заметки. Также этой заметкой можно поделиться в соцсетях. Так как я не любитель различных социалок, то этой возможностью не пользуюсь.
Также в данном ридере присутствует поиск выделенного текста в википедии. Это удобно, если вы хотите узнать больше о каком-либо слове. Читалка очень шустро реагирует на движения, и вы не ощущаете дискомфорта при пролистывании страниц.

Недостатки
В каждом продукте есть свои недостатки, данная читалка их также имеет. И если честно, то эти недостатки мне очень не нравятся, и автоматически для меня данная читалка упала в рейтинге. Об этих фактах умалчивают, дабы не испятнать крутой статус ридера.
Больше всего меня реально напрягает дата-кабель, который идет в поставке, длина которого составляет 25 см.
Интересно, что вообще можно сделать этим кабелем? Хорошо, что у меня был длинный дата-кабель под Nokia Lumia 710. Дело в том, что высота у моего ПК до USB портов составляет 20 см, в итоге ридер ложится ровно под сам системный блок и его нельзя переложить куда-либо.
Перейдем ко второй неприятной новости. Вы не можете выключить ридер!!! Да, да, вам не послышалось. Ридер выключить нельзя. Можно потушить экран, но он все равно будет сжирать батарею. У него есть кнопка power, которую необходимо зажать на 5-7 секунд, это позволит выключить экран, но не само устройство.
Мы можем только перевести устройство в режим сна. Подобно спящему режиму в ПК. На жалобы пользователей, как быть, если, например, нужно куда-то лететь, а устройство нельзя выключить, амазон выкрутился тем, что добавил возможность отключения всех сетей в устройстве на режим полета.
Не знаю, как вас, но меня это немного злит. Не люблю, когда у меня устройство все время включено. В последнее время я читаю ридер по дороге на работу и с работы. Это 1 час в день. Все стальное время батарея просто израсходуется понапрасну. На официальном сайте вы сможете увидеть информацию о том, что данная батарея может работать свыше 8-ми недель. Это откровенная ложь. За третий месяц я его заряжаю уже третий раз. Это выходит в среднем чуть меньше 3 недель. Учитывая тот факт, что как только пришел мне данный ридер, я практически не читал, он сел буквально за две недели. В итоге неважно, читаете вы или нет, но стабильно нужно будет раз в месяц (полтора, если ничего читать не будете) заряжать данную читалку. Если взять для примера мою старую читалку, то она у меня выдерживал 2 месяца гарантировано, если читать по часу в день. У меня никогда с ней не было проблем, что она сядет в дороге, или что я не знаю, какой заряд батареи у нее на данный момент. Ее проблема была в том, что она плохо работала с pdf и djvu-файлами.
Третья проблема данной читалки, это очень малое количество поддерживаемых форматов. Вам частенько может понадобиться конвертировать в формат AZW/AZW3 – Kindle Format 8. Так как я читаю книги, в основном, в формате pdf, в этом нет особой проблемы для меня лично. Но остаётся небольшой осадок, что множество книг нельзя прочитать, так как их не поддерживает данная читалка. Например, CHM, DJV, DJVU, EPUB, FB2 и другие.
Четвертая проблема, которая тесно связана с проблемой номер три, описанной выше, коснулась непосредственно меня. Данная читалка плохо масштабирует текст в pdf. Так как из-за постоянной работы за ПК я посадил свое зрение и из-за этого вынужден работать в очках, меня это сильно напрягает, так как текст получается маленький. Либо он масштабируется так, что не влезает на экран, и прокручивать каждое предложение очень неудобно. Смена режима шрифта тоже не помогает в данном случае. Почему-то данная проблема у меня наблюдается только с книгами в формате pdf.
Пятая проблема связана с самим материалом, из которого сделана читалка. На нем очень отчетливо видно следы пальцев при работе на лицевой панели, на задней панели. Экран в этом плане сделан получше. На нем не остаются отпечатки пальцев так, как на других частях устройства. Спасает только чехол, который я рекомендовал выше. Он позволяет избежать отпечатков пальцев на вашем устройстве.

Итоги
В целом читалка очень классная своими возможностями. Если бы не мелкие и неприятные недочеты, которые мне удалось обнаружить. Хотя вполне вероятно, что для некоторых эти нюансы не составят проблемы. В целом я бы поставил это читалке твердую оценку "4". В основном эта оценка получилась благодаря возможностям быстрых заметок и встроенного словаря, продолжительности работы данной читалки, а также благодаря просто шикарного дисплея. Если вас не пугают небольшие недочеты, которые описаны выше, рекомендую данную читалку. Она стоит тех денег, которые на неё будут или уже были потрачены.

Sunday, August 17, 2014

Переход на .NET Framework 4.5. Преимущества и недостатки

Плюсы перехода с .NET Framework 4.0 на .NET Framework 4.5 в для разработчиков WPF
Самом .NET Framework 4.5 претерпел серьезных изменений, по сравнению с 4-й версией фреймворка. Было сделано множество вещей, которые позволяют писать программный код более гибко; много возможностей, которые раньше поставлялись отдельно, теперь поставляются в паре с самим фреймворком. Теперь не нужно таскать с собой разные библиотеки, это позволит избежать одной популярной и неприятной проблемы, которая известна среди разработчиков как DLL hell. Разделение плюшек, которые могут принести новые возможности 4.5 фреймворка, я решил сделать в двух частях. Первая часть – это преимущество с точки зрения конечного пользователя, 2-я часть техническая и будет включать в основном те специфические вещи, которые позволят команде улучшить процесс разработки и написания кода.
Ribbon Control
В .NET Framework 4.0 для  работы с риббонами была доступна бесплатная библиотека RibbonControlsLibrary, которую можно было загрузить с codeplex. Она адаптирована для использования в .NET Framework 4.0, поэтому имеет множество заточенных возможностей, которые были специально адаптированы под конкретный фреймфорк. Риббоны позволяют создавать составные панели и писать софт по аналогии с Microsoft Office. Пример на рисунке ниже.
Начну с нескольких вариантов в пользу использования новых риббон-контролов, которые появились в WPF 4.5 (4.5 фреймворк). Во-первых, это пройдет для вашего проекта безболезненно по той причине, что пространства имен не изменились, контролы не изменились, они просто дополнились и подверглись небольшим изменениям.
Вторая причина замены – это то, что Ribbon-контролы, которые есть в вашем проекте, уже включены в состав самого фреймворка и не нуждаются в отдельных библиотеках. Это минус одна библиотека в поставку.
Третья причина менее значительна, чем две предыдущие, но она также достаточно интересна. Размер библиотеки, адаптированной под 4-й фреймфорк, практически в два раза больше аналогичной под фреймфорк 4.5.
Поэтому данная замена имеет место быть, так как позволит избавиться от одной лишней библиотеки и возложит всю работу на сам фреймворк. Мы же получим оптимизированную версию, которая будет предоставлять нам новые возможности, благодаря новому фреймворку.
VirtualizingPanel
Одна из самых популярных проблем при отображении большого количества данных в гридах и т.д. – это прокрутка данных гридов, чтобы они не подвисали. Ниже представлен пример такого грида с большим количеством данных, картинку которого я взял со stackoverflow, чтобы продемонстрировать, чем это чревато.
В старой версии фреймфорка мы могли только установить свойство IsVirtualizing и VirtualizationMode.  В простых случаях она спасает. Но в тех контролах, где есть группировка контролов, разного вида фильтры, это не особо помогает. В 4.5 фреймворк для панелей, наследуемых от VirtualizingPanel, добавилось несколько свойств, которые могут ускорить намного прорисовку контролов во время прокрутки.
  1. You can specify whether a VirtualizingPanel, such as the VirtualizingStackPanel, displays partial items by using the ScrollUnit attached property. If ScrollUnit is set to Item, the VirtualizingPanel will only display items that are completely visible. If ScrollUnit is set to Pixel, the VirtualizingPanel can display partially visible items.    
  2. You can specify the size of the cache before and after the viewport when the VirtualizingPanel is virtualizing by using the CacheLength attached property. The cache is the amount of space above or below the viewport in which items are not virtualized. Using a cache to avoid generating UI elements as they’re scrolled into view can improve performance. The cache is populated at a lower priority so that the application does not become unresponsive during the operation. The VirtualizingPanel.CacheLengthUnit property determines the unit of measurement that is used by VirtualizingPanel.CacheLength.
Асинхронная и синхронная валидация данных.
Добавлен новый интерфейс INotifyDataErrorInfo, который позволяет валидировать данные на форме асинхронно.
Для пользователей, по сути, больше нет других полезных вещей, которые они могут увидеть. Но теперь пора перечислить те вещи, которые упростят жизнь разработчикам.
Отложенный байндинг
Одной из новых фишек, которые затронули WPF и которые могут пригодиться для разработчиков, – это использование отложенного байндинга. Например, вы вводите какой-то текст в TextBox и хотите его изменять в другом месте. Вы по старинке устанавливаете UpdateSourceTrigger в PropertyChanged и получаете обновление после каждого обновления свойства (добавление символа, вставка текста, удаление символа и т.д.). А если у вас при этом используется, например, какой-то фильтр, то у вас на каждую букву будет попытка найти отфильтрованные данные для списка. Скажем, я ввел 3 буквы и у меня три раза перестроились какие-то мои отфильтрованные данные в списке. Благодаря свойству Delay мы можем указать отложенное время, через которое необходимо обновить, например, некий фильтр или проделать нужные нам действия. Например, если мы поставим для Delay значение 1500 мс, то наше свойство будет изменено спустя 1,5 сек. За это время мы можем ввести порядка 5-7 символов. Аналогичная возможность уже была сделана в библиотеке реактивных расширений Rx (англ. The Reactive Extensions (Rx)) под WPF. Там это уже было сделано. Но, к сожалению, библиотека реактивных расширений не настолько популярна в мире разработки ПО, а еще мене популярна она для WPF.
Async Methods for Dispatcher
В классе Dispatcher, который вы, наверняка, используете в своем проекте, наконец-то появились нормальные асинхронные методы.
  • InvokeAsync(Action)
  • InvokeAsync(Action, DispatcherPriority)
  • InvokeAsync(Action, DispatcherPriority, CancellationToken)
  • InvokeAsync<TResult>(Func<TResult>)
  • InvokeAsync<TResult>(Func<TResult>, DispatcherPriority)
  • InvokeAsync<TResult>(Func<TResult>, DispatcherPriority, CancellationToken)
Вы, вероятнее всего, скажете, что асинхронность уже была доступна в Dispatcher с помощью методов BeginInvoke/EndInvoke, и будете правы. Теперь Dispatcher можно вызывать в асинхронном режиме, не дожидаясь ответа. Пожалуй, остановлюсь на этом моменте белее детально, поскольку надеюсь, что это нюанс будет интересен WPF-разработчикам. Класс Dispatcher наконец то начал нормально работать с тасками (класс Task с библиотеки Task Parallel Library (TPL)). У нас появился новый класс DispatcherOperation, который возвращает нам метод InvokeAsync класса Dispatcher.
public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
    if (callback == null)
    {
        throw new ArgumentNullException("callback");
    }
    ValidatePriority(priority, "priority");

    DispatcherOperation operation = new DispatcherOperation(this, priority, callback);
    InvokeAsyncImpl(operation, cancellationToken);

    return operation;
}
Пример использования InvokeAsync приведен ниже.
private async Task TestNewDispatcherAsync()
{
    var doSomething = await Dispatcher.CurrentDispatcher.InvokeAsync<Task<string>>(DoSomething);

    var result = await doSomething;

    MessageBox.Show(result);
}
private async Task<string> DoSomething()
{
    await Task.Delay(1000);
    return "hi";
}
Это работает по одной простой причине, что в .NET 4.5 появились методы async/await, и мы можем оперировать с помощью класса Dispatcher работой с тасками. 
Я считаю, что это неплохой способ использовать возможности класса Dispatcher по максимуму. И новые расширения должны вам поспособствовать разрабатывать ваши приложения легко читаемыми и легкими в сопровождении. Это немаловажно в программировании.
Налажена работа с WeakEventManager
Небольшие изменения коснулись также класса WeakEventManager, который используется для того, чтобы избежать жесткой привязки к событиям, и не следить за тем, что мы вдруг забудем отписаться от события. Использовать вместо самописных реализаций, например.
Garbage Collector Improvements
Улучшилась сборка мусора с помощью GC. Появился так называемый Background Server GC.
Кратко о преимуществе с habrahabr: Обратная сторона луны
Server GC разделяет управляемую кучу на сегменты, количество которых равно количеству логических процессоров, используя для обработки каждого из них по одному потоку.
Т.к. Server GC делит управляемую кучу на несколько сегментов (каждый их которых обслуживает отдельный логический процессор), то в параллельной сборке мусора уже нет необходимости (если бы еще один поток запускался на др. логическом процессоре). Этот режим принудительно переопределяет параметр gcConcurrent. Если включен режим gcConcurrent, режим Batch будет препятствовать дальнейшей параллельной сборке мусора (!!!). Batch эквивалентен непараллельной сборке мусора на рабочей станции. При использовании такого режима характерна обработка больших (!!!) объемов данных.
Asynchronous Programming with async/await
Новый подход к разработке параллельных программ, используя ключевые слова async/await.
  • Task строит цепочку продолжений, которая увеличивается в соответствии с количеством задач, связанных последовательно, и состояние системы управляется через замыкания, найденные компилятором;
  • async/await строит машину состояний, которая не использует дополнительных ресурсов при добавлении новых шагов. Однако компилятор может определить больше переменных для сохранение в стеки машины состояний, в зависимости от вашего кода (и компилятора). В статье на MSDN отлично расписаны детали происходящего.
Если вкратце, то данный подход позволяет писать код, который будет работать в асинхронном режиме и при этом не нагружать основной GUI поток.
Использование CallerMemberNameAttribute
Данный код позволит избегать вызова PropertyChanged в передаче аргумента по умолчанию. Это лучше рассмотреть на примере.
public class EmployeeVM : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
        }
    }
}
Выше приведен код, присущий в 4-м фреймворке. А теперь приведу пример, как изменится наш код с CallerMemberName.
public class EmployeeVM : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }
}
Или, например, можно взять методы, которые реализованы в библиотеке Prism 5.0.
private string _author;
public string Author
{
    get { return _author; }
    set
    {
        _author = value;
        OnPropertyChanged(() => Author);
    }
}
Или же вот такой тип записи:
private string _author;
public string Author
{
    get { return _author; }
    set
    {
        SetProperty(ref _author, value);
    }
}
Set Default Culture
Установку культуры для AppDomain можно сделать в одну строку, используя свойство DefaultThreadCurrentCulture. Позволяет избавиться от грязных хаков в программе, которые позволяли считывать культуру как Private Field и заменять это значение. Теперь с этим не нужно заморачиваться, просто используем свойство, которое появилось в новом фреймворке и которое мы сейчас рассматриваем.
Zip Compression
Поскольку поддержка работы с zip-архивами добавлена в сам фреймворк, мы можем избавиться от сторонних библиоте, как, например, Ionic.Zip, SharpCompress, SharpZipLib и других, если такие имеются в проекте.
TPL (Task Parallel Library)
В библиотеку TPL добавлено множество методов, которых очень сильно не хватало в 4-й версии. Например, методы FromResult, Delay, Yield, GetAwaiter и ConfigureTaskAwaiter. 
Итоги
Перечисленные выше преимущества позволят вам взглянуть на разработку ваших программ с использованием .NET Framework 4.5 под другим углом. Если у вас используются, например, WCF сервисы, то вы можете строить операции, которые будут возвращать таски. Также для работы с БД есть возможность использовать EF 6.0 с его новыми возможностями, как асинхронность, поддержка enums и многое другое. Есть, конечно, и негативные стороны в этом всем. Например, если у вас используются Moq для юнит или интеграционного тестирования, то вам нужно посмотреть в сторону обновления до последней версии (на момент написания статьи это была версия 4.2) данной библиотеки, так как она очень неплохо, наконец-то, стала работать с асинхронностью. Также MS Test позволяет тестировать код, который использует таски с помощью ключевых слов async/await, не изобретая для этого "велосипедов", которые параллельное выполнение вашего кода делают последовательным. Наверное, больше проблем можно схлопотать, если использовать UIAutomation для покрытия вашего интерфейса Coded UI Tests. Если не ходить вокруг да около, то компания Microsoft сломала обратную совместимость в данном плане для Grid, List для поиска дочерних элементов, а также сломана работа с ScrollView для данных контролов. Вам нужно будет придумывать разные костыли, чтобы это обойти. Как говорится, не все так гладко, как хотелось бы, но в целом, данный переход оправдан, если только ваши клиенты не используют Windows XP. В .NET 4.5 нет поддержки Windows XP. Это большая проблема для тех, у кого множество клиентов использует до сих пор Windows XP. Таким разработчикам можно разве что посочувствовать в постоянной адаптации новых возможностей, так как даже в 4-м фреймворке, если у вас все работает в WPF, проверьте это же на XP, и вы будете приятно удивлены. А учитывая тот факт, что даже после того как Microsoft прекратила поддержку Windows XP, для того чтобы пользователи перешли на ту же Windows 7, для некоторых пользователей это может занять годы. Надеюсь, что обзор был не очень скучным, и если вы даже не собираетесь переводить ваш проект на новый фреймворк, я думаю вам будет интересно знать, что особенного там появилось.