Pull to refresh
4
0.2
Юрий Захаров @YuryZakharov

User

Send message
Но разве микросервисы не подразумевают, что любой микросервис в системе может быть написан на любой технологии и языке?

Подразумевают. Но не обязаны.
использовать его для создания большой системы будет проблематично?

Нет, если не ставить себе хипстерских целей.
Начать с того, что The Sun — тот еще источник достоверной информации…
«Нога в двери» это один из методов убеждения, который направлен на снижение диссонанса.


Нога в двери — это когда в проем Вашей двери поставил ногу бродячий торговец. И закрыть ее Вам уже сложнее.
Никакого диссонанса тут нет. Агрессия есть. А диссонанса — нет. Что с чем диссонирует? Вы понимаете термин «диссонанс»? А «не соответствует»? Похоже, что нет.
Даже в Вашей интерпретации нет диссонанса. Есть манипуляция клиентом для создания у него чувства ответственности и побуждение к покупке на этой почве. Все, ничего больше.

Хотя цели Вы своей добились, статья вызывает дисонанс.
Ох, ну, что ж Вы ерунду-то всякую пишете?
Примером когнитивного диссонанса можно считать басню Крылова «Лисица и виноград».

Нельзя. Это пример, скорее, фрустрации.

А вот сцена из «Бременских музыкантов», когда петух лает — как раз вызывает у зрителя К.Д.
Вот если бы лиса попробовала спелый и сочный на вид виноград, а тот оказался бы кислым — да, он самый, К.Д.
Видите разницу?
Сцена с пончиком тоже никаким боком к диссонансу не относится…

Как использовать когнитивный диссонанс в дизайне и маркетинге

Задача маркетолога — уменьшить диссонанс пользователей.

Это, и приведенный пример с веганским пончиком — не использование когнитивного диссонанса, а, как раз, наоборот, избавление от него. (Опять же, речь и тут у Вас идет совсем не о диссонансе, см. выше.)

Представьте, что вы работаете над онбордингом для своего продукта.

Это статья от маркетологов для маркетологов? Так им и так хорошо…

Ну, читайте же книги, там все написано.
Оно понятно, терминология завораживает, но использование ее без понимания — культ карго.

Пост — отличная лакмусовая бумажка!
Очень показательно, спасибо.
Я к тому, что из простоты системы не обязательно следует ее гибкость.
А не кажется ли Вам, что сложность и гибкость — суть понятия ортогональные?
А Раскукожку нельзя уволить по сокращению?
Если от сканера получать и единый pdf и кусочки?
Сканирует-то он все равно по частям…
А можно контракт научить ходить на random.org?
Там плюшки всякие, маяки, проверяемость…
Это чтобы с ГПСЧ не морочиться и предотвратить возможность описанной потенциальной атаки?
Ну, и по-настоящему случайные числа.
А потому, что Error возвращает удаленный сервер, вполне легитимный ответ и его надо обрабатывать. А Task может завалиться и по другой причине.
Что-то вроде :)
В том-то и дело, что не равноценны. Если Вы этого не видите, ну, что ж…
Про стиль и пальцы написали уже. У меня такое не то, что code review не прошло бы, даже commit завернуло бы.
Выше неудачное объяснение, громоздкое.
Смотрите, Вы говорите
If(false == b) {}
false — это константа, она ничему больше, кроме самой себя, равняться не может.
С этим, надеюсь, спорить не будете?
Так вот, странно семантически неверно сравнивать константу с чем-то. Что-то с константой- да, если это что-то может принимать разные значения.

Технически, никто Вам не запрещает писать так, как Вы пишете, ни компилятор, ни рантайм. Но читается это не очень…
Поэтому, собственно, весь остальной мир на шарпе и пишет if(value==null).

Про code style, naming conventions рассказывать?
Про семантику?

Сравните:
если мое_множество равно пустому_множеству то…
против
если пустое_множество равно моему_множеству то…

пустое множество не может равняться чему-то еще, оно одно такое, инициальный объект в этом типе.
То есть, стараться всунуть как можно больше в одну строчку, получая потенциальный рассадник ошибок и ухудшение понятности, это улучшение?
Не говоря уже о такой «ошибке присваивания, как
null = line;

Гипотетически, если тип приводится к bool, можно наворотить, но Вы же не пишете
if(b == false)
{
}
, правда?
А в чем преимущество присваивания в условии?
Тяжелое плюсовое детство?
Примерно так:
public interface ISomeService
{
    Task<Either<TradeError, Quote>> GetQuoteAsync(GetQuoteQuery query);
}
...
var result = await _service.GetQuoteAsync(query);
result.Match(SetQuoteError, SetQuote);
...

private void SetQuoteError(TradeError error)
{
    // do something
}

private void SetQuote(Quote quote)
{
    // do something
}





Или так
public interface ISomeService
{
    Task<Either<TradeError, Quote>> GetQuoteAsync(GetQuoteQuery query);
}

...
public async Task<Either<TradeError, QuoteModel>> GetQuoteModelAsync(GetQuoteQuery query)
        {
            var result = await _service.GetQuoteAsync(query.);
            return result.Bind(ToQuoteModel);
        }
...

private static QuoteModel ToQuoteModel(Quote source) => new QuoteModel{ ... };




Должно быть понятно, вроде… :)
Не то, чтобы моя реализация с нуля:
Как-то так
public class Either<TL, TR>
    {
        [DataMember]
        private readonly bool _isLeft;

        [DataMember]
        private readonly TL _left;

        [DataMember]
        private readonly TR _right;

        public Either(TL left)
        {
            _left = left;
            _isLeft = true;
        }

        public Either(TR right)
        {
            _right = right;
            _isLeft = false;
        }

        /// <summary>
        /// Checks the type of the value held and invokes the matching handler function.
        /// </summary>
        /// <typeparam name="T">The return type of the handler functions.</typeparam>
        /// <param name="ofLeft">Handler for the Left type.</param>
        /// <param name="ofRight">Handler for the Right type.</param>
        /// <returns>The value returned by the invoked handler function.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// </exception>
        public T Match<T>(Func<TL, T> ofLeft, Func<TR, T> ofRight)
        {
            if (ofLeft == null)
            {
                throw new ArgumentNullException(nameof(ofLeft));
            }

            if (ofRight == null)
            {
                throw new ArgumentNullException(nameof(ofRight));
            }

            return _isLeft ? ofLeft(_left) : ofRight(_right);
        }

        /// <summary>
        /// Checks the type of the value held and invokes the matching handler function.
        /// </summary>
        /// <param name="ofLeft">Handler for the Left type.</param>
        /// <param name="ofRight">Handler for the Right type.</param>
        /// <exception cref="System.ArgumentNullException">
        /// </exception>
        public void Match(Action<TL> ofLeft, Action<TR> ofRight)
        {
            if (ofLeft == null)
            {
                throw new ArgumentNullException(nameof(ofLeft));
            }

            if (ofRight == null)
            {
                throw new ArgumentNullException(nameof(ofRight));
            }

            if (_isLeft)
            {
                ofLeft(_left);
            }
            else
            {
                ofRight(_right);
            }
        }

        public TL LeftOrDefault() => Match(l => l, r => default(TL));
        public TR RightOrDefault() => Match(l => default(TR), r => r);
        public Either<TR, TL> Swap() => Match((Func<TL, Either<TR, TL>>) (Right<TR, TL>), Left<TR, TL>);

        public Either<TL, T> Bind<T>(Func<TR, T> f)
            => BindMany(x => Right<TL, T>(f(x)));

        public Either<TL, T> BindMany<T>(Func<TR, Either<TL, T>> f) => Match(Left<TL, T>, f);

        public Either<TL, TResult> BindMany<T, TResult>(Func<TR, Either<TL, T>> f, Func<TR, T, TResult> selector)
            => BindMany(x => f(x).Bind(t => selector(_right, t)));

        public static implicit operator Either<TL, TR>(TL left) => new Either<TL, TR>(left);
        public static implicit operator Either<TL, TR>(TR right) => new Either<TL, TR>(right);

        public static Either<TLeft, TRight> Left<TLeft, TRight>(TLeft left)
            => new Either<TLeft, TRight>(left);

        public static Either<TLeft, TRight> Right<TLeft, TRight>(TRight right)
            => new Either<TLeft, TRight>(right);

        public static Either<Exception, T> Try<T>(Func<T> f)
        {
            try
            {
                return new Either<Exception, T>(f.Invoke());
            }
            catch (Exception ex)
            {
                return new Either<Exception, T>(ex);
            }
        }
    }


Да хотя бы, чтобы не переучивать всю команду в середине проекта.
А так — здесь им идейку подкинул, тут структурку, глядишь, а они уже и сами упоролись куда надо.
Either и PipeTo

Можете предложить название лучше?

Ну, Either тут больше похож на ContinueWith, не? На мой взгляд. Не претендую. Просто CPS, как он есть…

По поводу
Either<TResult, Exception>
— дело вкуса, конечно. Я, например, в одном из проектов использую Either<TError, TResult>. И так это меня радует, неимоверно. Почти как у взрослых :), вынуждает разработчика обрабатывать оба варианта, иначе не скомпилируется.

Information

Rating
2,082-nd
Location
London, England - London, Великобритания
Registered
Activity