Pull to refresh
18
0
Антон Асташов @Astashov_Anton

User

Send message
Пусть у нас есть куча вложенных футур:

import 'package:stack_trace/stack_trace.dart';
import 'dart:async';

Future<Null> blah() async {
  throw 'foo';
}

void main() async {
  var result = await new Future(() async {
    await new Future(() async {
      await blah();
    });
  });
}


Если мы это запустим, то получим что-то типа такого:

Unhandled exception:
Uncaught Error: foo
Stack Trace:
#0      blah.<blah_async_body> (file:///Users/anton/projects/mixbook/photo_prints_web/blah.dart:7:3)
#1      Future.Future.microtask.<anonymous closure> (dart:async/future.dart:144)
#2      _microtaskLoop (dart:async/schedule_microtask.dart:43)
#3      _microtaskLoopEntry (dart:async/schedule_microtask.dart:52)
#4      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:394)
#5      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:414)
#6      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)

#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:895)
#1      _microtaskLoop (dart:async/schedule_microtask.dart:43)
#2      _microtaskLoopEntry (dart:async/schedule_microtask.dart:52)
#3      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:394)
#4      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:414)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)


Нифига не понятно, откуда мы пришли в blah() когда случилось исключение. Но если мы это обернем в Chain.capture:

Future<Null> blah() async {
  throw 'foo';
}

void main() {
  Chain.capture(() async {
    var result = await new Future(() async {
      await new Future(() async {
        await blah();
      });
    });
  }, onError: (error, chain) {
    print(chain.terse);
  });
}


мы получим вот такое:

blah.dart 7:3        blah.<async>
===== asynchronous gap ===========================
dart:async           _Completer.completeError
blah.dart 10:1       blah.<async>
===== asynchronous gap ===========================
dart:async           Future.Future.microtask
blah.dart            blah
blah.dart 14:15      main.<fn>.<async>.<fn>.<async>.<fn>.<async>
===== asynchronous gap ===========================
dart:async           Future.Future
blah.dart 13:17      main.<fn>.<async>.<fn>.<async>
===== asynchronous gap ===========================
dart:async           Future.Future
blah.dart 12:28      main.<fn>.<async>
===== asynchronous gap ===========================
dart:async           Future.Future.microtask
blah.dart            main.<fn>
package:stack_trace  Chain.capture
blah.dart 11:9       main


Такой себе нормальный стектрейс, хоть и от вложенных футур.
Я пишу на Дарте каждый день вот уже в течение 2-х лет (https://montagebook.com) — в основном фронтенд, но есть и бекенд сервисы. В целом нравится язык, не очень нравится политика гугла по отношению к нему и его PR (никакой PR, честно говоря). Если кратко, то для меня плюсы и минусы такие:

Плюсы:

* Concurrency. В языке с самых первых версий появились Futures и Streams, и поэтому все библиотеки их используют, и не изобретают свои велосипеды. Как правило, многие библиотеки и фреймворки поддерживают асинхронность с использованием этих Futures и Streams. Например, веб-фреймворк Redstone может принимать футуру в качестве response, тогда он подождет пока она завершится и потом сгенерирует response. MySQL драйвер возвращает результаты в Stream'е, а вставляет записи возвращая Future. Практически все аналоги в стандартной библиотеке работы с файловой системой имеют асинхронные аналоги. Для браузера, все API тоже обернуты в Streams или Futures. И вкупе с тем, что сейчас в язык добавили async/await и Zones (типа Node'вых Domains, но с поддержкой глобальных переменных на уровне зоны, типа Java's thread-local storage), все это сильно упрощает написание event-based веб сервисов и построение сложных приложений в вебе. Довольно легко можно писать в FRP-стиле, т.к. дофига чего возвращает Stream.

* Тулинг. Статический анализатор (хотя язык интерпретируемый — никакого compile-time!), линтер, менеджер пакетов, приличный автоформаттер, хороший unit-test фреймворк (опять же — отлично работает с асинхронными тестами), и еще куча всего. IDE работает хорошо, go to definition, find usages, рефакторинг, все это есть. Статический анализатор особенно хорош — это по сути headless IDE. Благодаря анализатору, я, например, сделал crossdart.info, который содержит исходники SDK и всех пакетов из центрального репозитория и ссылки между ними (например, crossdart.info/p/sdk/1.12.1/async/future.dart.html#line-182), а также хромовый плагин, который добавляет «go to definition» и «find usages» функциональность в пулл реквесты на гитхабе — ( crossdart.info/demo.html ), очень удобно теперь делать код ревью на проекте.

* Нормальная семантика языка (в отличие от JavaScript) — lexical scope, strong typing, вывод типов (локальный, правда), классы/интерфейсы/джереники (дженерики правда на уровне классов, не методов, тут TypeScript рулит больше)

* Довольно легко дебажить — дебаггер работает в IDE более-менее хорошо (особенно в серверных приложениях, с браузером бывают глюки), есть Observatory — инструмент для профайлинга и дебага уже работающих процессов — можно подключиться к процессу и поставить брейкпоинт, посмотреть CPU или Memory profile, посмотреть метрики, и пр. Довольно просто дебажить даже асинхронный код — благодаря зонам, если обернуть асинхронный кусок в Chain.capture из пакета stack_trace, то можно получить нормальный читаемый стек трейс даже в коде, состоящем из одних коллбеков и футур.

Минусы:

* Язык довольно консервативен, хочется больше современных плюшек, типа type aliases, non-nullable types, method generics, immutable value objects — вот этого всего. Справедливости ради, они вроде начинают копать в сторону non-nullable types и method generics.

* Никакой PR со стороны гугла, плохая репутация, маленькое коммьюнити. Гугл довольно активно использует Dart для внутренних нужд, и вектор развития языка похоже сильно смещен на удовлетворение нужд внутренних гугловых команд (Ads, Angular, и прочих).

* Нету консольного REPLа, нету горячего обновления кода.

В целом, язык дает довольно неплохой баланс между строгостью языка, легкостью освоения и доступными инструментами.
Плюсую, во фронт-енде довольно много хороших примеров использования FRP (на сайте Elm, например), было бы круто найти хорошую книгу как это можно это еще применять на бекенде, с базами данных, application серверами и вот этим всем.
Только не конструкторы типов, а конструкторы значений (value constructors). Конструктор типов — это Bool
Om клевый. Но он еще сильно альфа, из документации только исходники, мало примеров, и пока не очень понятно как вообще правильно строить приложения на нем, да и API меняется довольно часто. Но все равно он чертовски многообещающий, и обязательно стоит на него посмотреть и поиграться.
Пока что лучшая IDE для ClojureScript. Поиск по документации, инлайн доки, jump-to-definition, возможность прямо-вот-тут-в-коде выполнить тут же написанные функции в контексте подсоединенного браузера — все это работает прямо из коробки. Красота!
В MacOSX можно делать так: «sleep 3; say 'completed'». Если у вас, конечно, звук включен.
С апреля этого года уже если за 50$k переваливает — то нужен паспорт сделки.
Оказывается, Nokia не только увольняет. На Ovi maps она даже набирает — careers.stackoverflow.com/jobs/11365/software-testing-engineer-with-scripting-skills-nokia
А вот про это мне было бы очень интересно почитать. Пишите, уверен, многие найдут это интересным и полезным.
Это да, но когда я выбирал банк, я выбрал тот, что через дорогу от дома. Если перееду — то просто переведу паспорт сделки в другой банк. Который тоже по возможности будет через дорогу. А переезды, думаю, не так часто случаются.
Ну в первый раз действительно непросто. А потом в общем-то за час все это провернуть. Предположим, вы работаете на иностранного заказчика, он каждый месяц шлет вам деньги. У нас уже есть акты за прошлые месяцы, все необходимые документы из банка за прошлые месяцы. Поэтому:
1. Меняем дату и сумму в акте, шлем заказчику на подпись
2. Заказчик подписывает акт, отсылает назад, также отсылает деньги.
3. Когда приходят деньги, банк присылает письмо-уведомление, подставляем во всех справках/документах данные из уведомления (там в основном даты и суммы, в общем-то можно даже скриптик накатать, который это делать будет, потому что уведомления все шаблонные)
4. Печатаем все эти документы, несем в банк к валютному контролю. Он продает валюту на рублевый счет с транзитного, можем сразу там же деньги сразу снять.
Все. Потратить час-два раз в месяц, зато получать честную и белую зарплату. А это тоже важно, потому что:
а) без хорошей зарплаты в Европу/США и другие страны, где виза нужна, визу скорее всего не дадут.
б) кредит тоже не взять, а без кредита купить что-то большое (например, дом/квартиру) не реально
в) да и как-то спокойнее, когда знаешь, что ты живешь по закону и ничего не нарушаешь
Time Machine на нее бэкапится прекрасно!
По TDD — сначала тест не должен пройти — он должен быть красным. После того, как вы добавите код, запустите еще раз тест — он должен быть успешен. Таким образом если у вас он до написания кода зеленый, или после написания кода красный — значит тест не правильный (при условии что код верен).
А, и самое главное — ни на что не отвлекаемся в течение 25 минут. Вообще. Если даже телефон звонит — берем трубку, обещаем перезвонить, ставим напоминание позвонить в течение 5 минут перерыва. Если пришлось вдруг надолго прерваться — этот помидор не учитываем, ставим опять таймер на 25 минут и начинаем сначала.

Очень хорошо эта техника работает во время приближающихся дедлайнов — очень высокая производительность. Но лично для меня так работать все время тяжело.
25 минут работаем, 5 отдыхаем. Получается 30 минут — это одна помидора. :) Перед работой составляем план со списком заданий, каждое задание оцениваем в помидорах — сколько помидоров требует это задание. Потом ставим таймер на 25 минут — делаем задание, потом 5 минут отдыхаем, 25 минут работаем, 5 отдыхаем, таким образом выполняя задания, один за одним. В процессе отмечаем сколько нам потребовалось помидор для выполнения задания, и сколько мы планировали.

Это в кратце. Подробнее тут — http://www.pomodorotechnique.com
А у меня не получилось переехать на Rails 3, уткнулся в это:
https://rails.lighthouseapp.com/projects/8994/tickets/5557-rails-300-yield-wont-show-block-contents-in-render-layout-if-it-is-placed-after-render-partial
Надеюсь, скоро починят…
Да это просто праздник какой-то! Сохраняющийся undo и colorcolumn. Ееееее! :)
 Мне больше нравятся другие каптчи — например, negative captcha (идея, пример реализации в виде Rails плагина). Несравненно большее удобство для пользователя (потому что она вообще не заметна для него) при немного меньшей, возможно, эффективности.

Information

Rating
Does not participate
Location
Palo Alto, California, США
Date of birth
Registered
Activity