на самом деле мы поддержали достаточно большую часть инспекций из jshint, а также все статические ошибки strict mode (кроме тех, которые можно отследить только в рантайме). Думаю, по этому поводу еще будет отдельная статья.
Качайте 9ю версию и пробуйте :)
Ровно год как юзаю 1020.
Мой итог: мерзость полная! Жду когда появятся лишние деньги, чтобы купить нормальный ведрофон.
Единственный плюс — камера, но и этот плюс оскверняется тем, что камера жутко тормозит.
Несмотря на уверения обладателей виндофонов, винда жутко тормозит. Не то чтобы списки тормозят как на одноядерном андроиде, тормозит возобновление приложений. И это БЕСИТ. Мне вчера позвонили по вайберу, отобразился экран со звонком — я нажал Ответить, вайбер решил возобновить состояние, и это заняло около 20 секунд, само собой звонок оборвался.
Как я уже сказал, тормозит модная нокиевская камера. Я почти никогда не успеваю сделать важные внезапные снимки. Тормозит автофокус (до 5 секунд). Если мне нужно чтото срочно сфоткать, автофокус промахивается в 4 из 5 случаев, рядом люди спокойно фоткают на айфоны и андроиды.
Тормозит возобновление контактика. Тормозит скайп.
Убогий софт. Весь. Нет нормального плеера. О да! В 8.1 в плеере наконецто можно перематывать треки на прогресс баре! Чудо! Нельзя назначить альтернативный плеер по умолчанию. Изза этого при клике по панели плеера (та что наверху экрана) всегда открывается стандартный мерзкий плеер. КАК такое могли написать в майкрософте, я не понимаю. Мой идеал PowerAMP на андроиде. На WP нет даже близко такого плеера.
Убогие браузеры.
Отсутствие доступа к внутренней памяти. Насколько я помню, я не мог скачать через браузер pdf в определенное место и потом открыть его вьювером. Можно было сказать и открыть только сразу. После закрытия временный файл терялся.
Убогий доступ к памяти телефона на компе. Очень криво реализованный MTP, 9 из 10 попыток открыть каталог с фотками заканчивается Device is busy, try later.
Встроенная звонилка не умеет искать по записной книге по т9, а внешние звонилки не умеют набирать коды USSD, я должен держать 2 звонилки, первая, в которой удобно искать абонентов, вторая, в которой можно проверить баланс. Причем история звонков у них синхронизироваться никак не может! Убицца.
Shazam запускается по 20-30 секунд, когда трек уже успевает кончиться, хотя даже на моем древнем incredible s это было быстрее, и распознавалось на нем все, а на винфоне только 1 из 3 раз.
Через одно место проигрывает видео в вебе. Например в контактике нельзя посмотреть видео с коуба.
Долбанутая панель настроек в новой 8.1. Ниче нельзя настроить, мне нахрен не нужна кнопка блютуса, при этом наоборот нужна кнопка 3g. Хрен там.
Из явных проблем:
периодически пропадает связь 3g/4g, лечится выключением/включением оной.
После обновления до 8.1 тел все время виснет и перезагружается. Что меня не один раз уже подставило, когда я спал и мне должны были позвонить, а так же просыпал будильник. ПРиходится делать ресет со сбросом времени. Происходит раз в 2-3 дня.
Перезагружается 3-4 раза в день.
Плюсы: камера фоткает и снимает действительно хорошо, несмотря на то, что тормозит. Но бесит, что при съемке видео нельзя принудительно фокусировать пальцем. Изза этого запорол кучу видео.
Последние 2 недели летит Error 200 OK через 2-3 секунды после коннекта. Да и вообще интерфейс убого остал от 2014 года. Приделали толпу свистелок, а нормально поддержать самый популярный мессадж сервис не могут, нет нормального отображения вложений, нет нормального цитирования, форвардинга сообщений. Куча чисто визуальных косяков в отрисовке интерфейса. Вроде бы QIP уже не школьники давно пишут.
Я бы не отказался от нормального десктоп мессенджера для ВК, сейчас юзаю квип для этого, но там такая толпа косяков, весь кривой, косой, коннект отваливается постоянно, но альтернатив не нашел
Сделали центр уведомлений — но его нельзя настроить. Мне не нужен Bluetooth, зато нужно быстро управление GPRS, его в этом центре нет.
Из апдейта радует только swype подобный ввод — действительно классно работает.
+100.
Одна из причин, почему следующий телефон я себе куплю на ведроиде — на винфоне нет адекватного плеера, и судя по всему никогда не будет. Никакие приблуды типа xbox music не спасают. До этого на андроиде был купленный Poweramp — вот эталон музыкального плеера как в плане эргономики так и в плане функциональности.
Люмия 1020 у меня почти год, с каждым месяцем все больше и больше негатива у меня к винфону, хотя покупал по предзаказу и именно по причине свалить с мерзкого тормозящего андроида. Однако и винда тоже адски тормозит, причем еще сильнее чем одноядерный incredible s. Дабы не быть голословным — периодически разные приложения запускаются по 10 секунд (vk, навигатор, и разные другие), а зачастую и вылетают без разумных объяснений. Да возьмем нативное приложение камеры. Казалось бы камера на камерофоне — главная его фишка, должна работать быстро. Однако в 95% случаев, когда мне надо заснять какойто момент, я не успеваю это сделать изза долгого запуска камеры. Пример: я стоял в салоне сотовой связи и из окна увидел, как менты остановили затонированную копейку. Я решил сфоткать и зажал кнопку камеры. Пока запускалась камера, менты успели достать прибор замера тонировки, замерить тонировку и уйти писать протокол. Сфоткать я так ничего и не успел.
Конечно, по сравнению с дотнетом для меня это «вырвиглаз», но все это изза остутствия рефлексии. Однако, оно имеет право на жизнь. Я думаю, вам стоит попробовать заюзать какой нибудь из этих контейнеров и попробовать «принудить» себя рассуждать в терминах зависимостей, исключив мысли о явном создании компонентов приложения и протаскивании их через множество слоев. Через некоторое время вы осознаете, что это очень мощный подход, который позволяет писать очень чистый и минимально избыточный код (опять же с поправкой на возможности С++).
не не не. Я вам в первом комменте указал, что при таком подходе, все создается через IoC контейнер! В том числе и ваши клиенты. Как раз этот подход избавляет от написания кучи фабрик у прочего шлакокода, который нужен только для инфраструктуры.
При использовании IoC все классы, которым требуются зависимости, создаются через контейнер, при этом он сам занимается разруливанием того, что нужно передать в конструктор — именно для этого и существует IoC. Выглядит примерно так:
//некоторый entry point вашего приложения:
var container = new Container();
container.Register<DeviceWithSpecificMethod1>().AsSelf().AsImplementedInterfaces().SingleInstance();
container.Register<DeviceWithSpecificMethod2>().AsSelf().AsImplementedInterfaces().SingleInstance();
container.Register<ClientFor2SpecificDevices>().AsSelf().AsImplementedInterfaces().SingleInstance();
container.Build();
// гдето в другом месте
ClientFor2SpecificDevices client = container.Resolve<ClientFor2SpecificDevices>();
// здесь вы получили ваш клиент, в который автоматически попали нужные устройства, заметьте, вы нигде не написали new
Единственное — придется протаскивать этот самый контейнер. Однако можно этого избежать, если создавать автоматически стартуемые компоненты (большинство контейнеров это умеют). Тогда весь ваш код будет работать через автоматический инжекшн.
Если вы не верите в такой подход — то могу сказать, что именно так написан Решарпер, а в нем не один миллион строк кода. Правда мы используем свой компонент контейнер, заточенный под наши нужды.
Более того такой подход позволяет реализовывать полиморфизм еще одним более гибким методом, не используя виртуальные методы языка. Точнее мы не заменяем полиморфизм языка, а дополняем его в тех местах, где использовать его по некоторым причинам нельзя или проблемно. В общем тема отдельной одной статьи, в который раз оправдываюсь на Хабре, что нет времени ее написать)
Более того, это не отменяет возможности получить оба этих устройства (или 5, если брать второй пример) в одном списке, если вам не требуются эти самые специфические методы, то мы просто инжексим IEnumerable<IDevice>
Если у вас есть РАЗНЫЕ с точки зрения типа устройства, т.е. у вас есть
— устройство DeviceWithSpecificMethod1 с методом Method1()
— устройство DeviceWithSpecificMethod2 с методом Method2()
и у вас есть клиент, которому нужны ОБА этих устройства, причем нужны для вызова именно этих СПЕЦИФИЧЕСКИХ методов Method1 и Method2
то да, вы просто инжектите 2 параметра в конструктор указывая явно эти 2 типа
public ClientFor2SpecificDevices(DeviceWithSpecificMethod1 dev1, DeviceWithSpecificMethod2 dev2) {
dev1.Method1();
dev2.Method2();
}
Не вижу в этом ничего плохого. Более того, если у вас есть на каждый из этих типов по несколько экземпляров устройств, например 2 устройства DeviceWithSpecificMethod1 и 3 устройства DeviceWithSpecificMethod2, то просто берем и инжектим коллекции:
public ClientFor2SpecificDevices(IEnumerable<DeviceWithSpecificMethod1> devList1, IEnumerable<DeviceWithSpecificMethod2> devList2) {
foreach(var dev1 in devList1) {
dev1.Method1();
}
foreach(var dev2 in devList2) {
dev2.Method2();
}
}
Погодите. Мне кажется, вы не до конца осознаете принцип DI.
> В списке присутствуют классы, реализующие эти интерфейсы и дополняющие их своими специфическими методами(читай — новыми)
Если есть такой класс, значит для него есть специфический клиент, который явно этот метод должен вызывать, верно? Значит сделайте в этом клиенте инжект именно этого специфического типа, в чем проблема?
class ClientToCallSomeSpecificMethod
{
public ClientToCallSomeSpecificMethod(DeviceWithVerySpecificMethod device)
{
device.SpecificMethod();
}
}
Я не знаю как с этим обстоят дела в С++ (со времен универа не писал на нем), но в большинстве случаев такая проблема легко решается через Dependency Injection.
В частости в дотнете я использую компонент контейнеры (Autofac например), который резолвит зависимости сам. Для вашего примера:
есть интерфейс IDevice. Есть классы для разных датчиков, реализущих этот интерфейс. Мы регистрируем все эти классы в контейнере.
Теперь о клиентах. Как вы сказали, клиенты могут требовать различные устройства, и различные их комбинации. Проще всего (и констистентнее) внедрять зависимость через конструктор. Причем внедрять можно различные агрегаты — как непостредственно типы, так и их коллекции, а также функторы от них — например фабрики. Пример:
class TemperatureDisplay
{
public TemperatureDisplay(TemperatureSensor sensor)
{
mySensor = sensor;
}
}
class AllSensorInfoDisplay
{
public AllSensorInfoDisplay(IEnumerable<IDevice> allSensors)
{
/// ...
}
}
В первом случае мы запросили только температурный датчик, во втором мы запросили все датчики в системе. Клиенты при этом подхоже нужно тоже создавать через контейнер, чтобы он смог внедрить зависимости.
Будет лучше, если для даже конкретных реализаций вы сделаете по интерфейсу типа ITemperatureSensor со всеми нужными методами и будете инжектить уже интерфейс. Это как минимум признак хорошего тона, плюс ко всему повышает гибкость системы (хотя насчет С++ не знаю, в связи с отсутвствием интерфейсов и наличием множественного наследование там скорее всего другие практики).
Еще один пункт — бывают ситуации, когда нужно заинжектить набор объектов по какому либо признаку, для нашего примера — предположим, могут быть устройства, имеющие расположение, т.е. метод GetPosition(), и мы хотим сделать клиента, который сможет взять все такие устройства и отобразить их позиции. При обычном подходе, пришлось бы писать кучу кода с выборкой таких устройсв и т.д. При инъекции сделаем следующее: добавим интерфейс
interface IPositionedDevice : IDevice {
Position GetPosition();
}
И реализуем его во всех нужных классах устройств, имеющих расположение. Тогда в классе клиенте достаточно заинжектить список IEnumerable<IPositionedDevice> — и мы получим все устройства с позицией.
Как я уже сказал — я использую Autofac, при этом я написал свой регистратор типов, которых работает на атрибутах. Т.е. я не регистрирую новые классы руками, а просто добавляю аттрибут Component у класса. Как такое делает в С++ опять же не скажу.
Насчет жесткого прогона «школа-вуз-работа» — довольно весомая причина этого для молодых людей — армия. Если не получается избежать армии честными способами в школе и родители явным образом не «помогли» тебе в этом, то поступая в вуз получаешь отсрочку. А там уже и сам становишься более взрослым, и есть возможность найти самому способы не пойти в армию.
С этим не поспоришь, тем более за 2 года как я закончил его кол-во поступающих увеличилось, соотвественно и требования возросли, дабы ограничить поток.
Если есть возможность поступить в Академический университет — то ее нельзя упускать. По-моему наблюдению (я его закончил), просто работая 2 года (а не учась), средний студент не получит и десятой части как фундаментальных так и технологических знаний, которые буквально впихивают в тебя за 2 года в АУ. Нагрузка большая, но оно того стоит. Ну и плюс это шанс продлить на 2 года студенческую жизнь, а для некоторых пожить и потусить в общаге) у меня за эти 2 года осталось дофига классных воспоминаний.
Качайте 9ю версию и пробуйте :)
Мой итог: мерзость полная! Жду когда появятся лишние деньги, чтобы купить нормальный ведрофон.
Единственный плюс — камера, но и этот плюс оскверняется тем, что камера жутко тормозит.
Несмотря на уверения обладателей виндофонов, винда жутко тормозит. Не то чтобы списки тормозят как на одноядерном андроиде, тормозит возобновление приложений. И это БЕСИТ. Мне вчера позвонили по вайберу, отобразился экран со звонком — я нажал Ответить, вайбер решил возобновить состояние, и это заняло около 20 секунд, само собой звонок оборвался.
Как я уже сказал, тормозит модная нокиевская камера. Я почти никогда не успеваю сделать важные внезапные снимки. Тормозит автофокус (до 5 секунд). Если мне нужно чтото срочно сфоткать, автофокус промахивается в 4 из 5 случаев, рядом люди спокойно фоткают на айфоны и андроиды.
Тормозит возобновление контактика. Тормозит скайп.
Убогий софт. Весь. Нет нормального плеера. О да! В 8.1 в плеере наконецто можно перематывать треки на прогресс баре! Чудо! Нельзя назначить альтернативный плеер по умолчанию. Изза этого при клике по панели плеера (та что наверху экрана) всегда открывается стандартный мерзкий плеер. КАК такое могли написать в майкрософте, я не понимаю. Мой идеал PowerAMP на андроиде. На WP нет даже близко такого плеера.
Убогие браузеры.
Отсутствие доступа к внутренней памяти. Насколько я помню, я не мог скачать через браузер pdf в определенное место и потом открыть его вьювером. Можно было сказать и открыть только сразу. После закрытия временный файл терялся.
Убогий доступ к памяти телефона на компе. Очень криво реализованный MTP, 9 из 10 попыток открыть каталог с фотками заканчивается Device is busy, try later.
Встроенная звонилка не умеет искать по записной книге по т9, а внешние звонилки не умеют набирать коды USSD, я должен держать 2 звонилки, первая, в которой удобно искать абонентов, вторая, в которой можно проверить баланс. Причем история звонков у них синхронизироваться никак не может! Убицца.
Shazam запускается по 20-30 секунд, когда трек уже успевает кончиться, хотя даже на моем древнем incredible s это было быстрее, и распознавалось на нем все, а на винфоне только 1 из 3 раз.
Через одно место проигрывает видео в вебе. Например в контактике нельзя посмотреть видео с коуба.
Долбанутая панель настроек в новой 8.1. Ниче нельзя настроить, мне нахрен не нужна кнопка блютуса, при этом наоборот нужна кнопка 3g. Хрен там.
Из явных проблем:
периодически пропадает связь 3g/4g, лечится выключением/включением оной.
После обновления до 8.1 тел все время виснет и перезагружается. Что меня не один раз уже подставило, когда я спал и мне должны были позвонить, а так же просыпал будильник. ПРиходится делать ресет со сбросом времени. Происходит раз в 2-3 дня.
Перезагружается 3-4 раза в день.
Плюсы: камера фоткает и снимает действительно хорошо, несмотря на то, что тормозит. Но бесит, что при съемке видео нельзя принудительно фокусировать пальцем. Изза этого запорол кучу видео.
Из апдейта радует только swype подобный ввод — действительно классно работает.
Одна из причин, почему следующий телефон я себе куплю на ведроиде — на винфоне нет адекватного плеера, и судя по всему никогда не будет. Никакие приблуды типа xbox music не спасают. До этого на андроиде был купленный Poweramp — вот эталон музыкального плеера как в плане эргономики так и в плане функциональности.
Люмия 1020 у меня почти год, с каждым месяцем все больше и больше негатива у меня к винфону, хотя покупал по предзаказу и именно по причине свалить с мерзкого тормозящего андроида. Однако и винда тоже адски тормозит, причем еще сильнее чем одноядерный incredible s. Дабы не быть голословным — периодически разные приложения запускаются по 10 секунд (vk, навигатор, и разные другие), а зачастую и вылетают без разумных объяснений. Да возьмем нативное приложение камеры. Казалось бы камера на камерофоне — главная его фишка, должна работать быстро. Однако в 95% случаев, когда мне надо заснять какойто момент, я не успеваю это сделать изза долгого запуска камеры. Пример: я стоял в салоне сотовой связи и из окна увидел, как менты остановили затонированную копейку. Я решил сфоткать и зажал кнопку камеры. Пока запускалась камера, менты успели достать прибор замера тонировки, замерить тонировку и уйти писать протокол. Сфоткать я так ничего и не успел.
вот несколько фреймворков, которые я нагуглил:
— code.google.com/p/wallaroo/ — выглядит достаточно ужасно
— code.google.com/p/hypodermic/ — вполне неплохо
— github.com/phs/sauce — тоже вполне ок
Конечно, по сравнению с дотнетом для меня это «вырвиглаз», но все это изза остутствия рефлексии. Однако, оно имеет право на жизнь. Я думаю, вам стоит попробовать заюзать какой нибудь из этих контейнеров и попробовать «принудить» себя рассуждать в терминах зависимостей, исключив мысли о явном создании компонентов приложения и протаскивании их через множество слоев. Через некоторое время вы осознаете, что это очень мощный подход, который позволяет писать очень чистый и минимально избыточный код (опять же с поправкой на возможности С++).
Вот тут вроде вполне годный цикл статей про разные контейнеры в С++
ledentsov.de/2014/01/01/quest-for-dependency-injection-library-part2-some-sauce/
При использовании IoC все классы, которым требуются зависимости, создаются через контейнер, при этом он сам занимается разруливанием того, что нужно передать в конструктор — именно для этого и существует IoC. Выглядит примерно так:
Единственное — придется протаскивать этот самый контейнер. Однако можно этого избежать, если создавать автоматически стартуемые компоненты (большинство контейнеров это умеют). Тогда весь ваш код будет работать через автоматический инжекшн.
Если вы не верите в такой подход — то могу сказать, что именно так написан Решарпер, а в нем не один миллион строк кода. Правда мы используем свой компонент контейнер, заточенный под наши нужды.
Более того такой подход позволяет реализовывать полиморфизм еще одним более гибким методом, не используя виртуальные методы языка. Точнее мы не заменяем полиморфизм языка, а дополняем его в тех местах, где использовать его по некоторым причинам нельзя или проблемно. В общем тема отдельной одной статьи, в который раз оправдываюсь на Хабре, что нет времени ее написать)
IEnumerable<IDevice>
— устройство DeviceWithSpecificMethod1 с методом Method1()
— устройство DeviceWithSpecificMethod2 с методом Method2()
и у вас есть клиент, которому нужны ОБА этих устройства, причем нужны для вызова именно этих СПЕЦИФИЧЕСКИХ методов Method1 и Method2
то да, вы просто инжектите 2 параметра в конструктор указывая явно эти 2 типа
Не вижу в этом ничего плохого. Более того, если у вас есть на каждый из этих типов по несколько экземпляров устройств, например 2 устройства DeviceWithSpecificMethod1 и 3 устройства DeviceWithSpecificMethod2, то просто берем и инжектим коллекции:
> В списке присутствуют классы, реализующие эти интерфейсы и дополняющие их своими специфическими методами(читай — новыми)
Если есть такой класс, значит для него есть специфический клиент, который явно этот метод должен вызывать, верно? Значит сделайте в этом клиенте инжект именно этого специфического типа, в чем проблема?
В частости в дотнете я использую компонент контейнеры (Autofac например), который резолвит зависимости сам. Для вашего примера:
есть интерфейс IDevice. Есть классы для разных датчиков, реализущих этот интерфейс. Мы регистрируем все эти классы в контейнере.
Теперь о клиентах. Как вы сказали, клиенты могут требовать различные устройства, и различные их комбинации. Проще всего (и констистентнее) внедрять зависимость через конструктор. Причем внедрять можно различные агрегаты — как непостредственно типы, так и их коллекции, а также функторы от них — например фабрики. Пример:
В первом случае мы запросили только температурный датчик, во втором мы запросили все датчики в системе. Клиенты при этом подхоже нужно тоже создавать через контейнер, чтобы он смог внедрить зависимости.
Будет лучше, если для даже конкретных реализаций вы сделаете по интерфейсу типа ITemperatureSensor со всеми нужными методами и будете инжектить уже интерфейс. Это как минимум признак хорошего тона, плюс ко всему повышает гибкость системы (хотя насчет С++ не знаю, в связи с отсутвствием интерфейсов и наличием множественного наследование там скорее всего другие практики).
Еще один пункт — бывают ситуации, когда нужно заинжектить набор объектов по какому либо признаку, для нашего примера — предположим, могут быть устройства, имеющие расположение, т.е. метод GetPosition(), и мы хотим сделать клиента, который сможет взять все такие устройства и отобразить их позиции. При обычном подходе, пришлось бы писать кучу кода с выборкой таких устройсв и т.д. При инъекции сделаем следующее: добавим интерфейс
И реализуем его во всех нужных классах устройств, имеющих расположение. Тогда в классе клиенте достаточно заинжектить список
IEnumerable<IPositionedDevice>
— и мы получим все устройства с позицией.Как я уже сказал — я использую Autofac, при этом я написал свой регистратор типов, которых работает на атрибутах. Т.е. я не регистрирую новые классы руками, а просто добавляю аттрибут Component у класса. Как такое делает в С++ опять же не скажу.