Обновить
2
Юрий Захаров@YuryZakharov

Пользователь

0,1
Рейтинг
Отправить сообщение
Пост — отличная лакмусовая бумажка!
Очень показательно, спасибо.
Я к тому, что из простоты системы не обязательно следует ее гибкость.
А не кажется ли Вам, что сложность и гибкость — суть понятия ортогональные?
А Раскукожку нельзя уволить по сокращению?
Если от сканера получать и единый 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>. И так это меня радует, неимоверно. Почти как у взрослых :), вынуждает разработчика обрабатывать оба варианта, иначе не скомпилируется.
Можно позанудствовать?
Спасибо.
ById требует соблюдения некоторых соглашений. Что-то облегчили, в чем-то добавили сложности
Ваш Either не совсем та структура (монада, если угодно) Either, которая обычно используется в ФП…
Ну, и названия типа MaybeWhere глаз немного режут.
А вообще радует Ваш подход
Вот это
$obj->Русские_буквы

— зло.
Можете объяснить, зачем Вам кириллица в именах?
Вот так, что без этого совсем никуда…
Если это про «национальную гордость великороссов», то представьте, что вам достался на поддержку китайский проект, а они гордыми оказались…
Про
«svoistvo»
вообще промолчу… Чем «property» не угодило? Английского не знаете?
Javascript изучаете, изучите азы английского заодно. Не трудно и пригодится много где еще.

Общее впечатление от Вашего подхода — нет структуры, каша какая-то.
Уж простите за такую критику.
Вы бы знали, сколько подобной каши я повидал…
Но дело Ваше. Чем больше пионэров, тем больше моя ценность, как специалиста.
/* Это сарказм и ирония, если что */
Вы троллите так?
  create table [dbo].[order]
  (
	[id] [int] primary key clustered,
	[customerId] [int] not null foreign key references [dbo].[customer]([id]),
	[deliveryAddressId] [int] not null foreign key references [dbo].[address]([id]),
	[date] [datetime] not null
  );

  create table [dbo].[orderItem]
  (
	[orderId] [int] not null foreign key references [dbo].[order]([id]),
	[itemId] [int] not null foreign key references [dbo].[goods]([id]),
	[price] [money] not null
  );

Обвязку из [customer], [address], [customerHistory] и прочего сами додумаете?
Адресов на клиента будет в среднем 1.01, имен — 1.0000000000001
Запрос тоже написать или основы поизучаете?
И да, если у Вас на таком join'е все заткнется, научите, как такого достичь?

Информация

В рейтинге
3 611-й
Откуда
London, England - London, Великобритания
Зарегистрирован
Активность