Он не писал, что нельзя совмещать, вы неверно прочли. Он написал, что они не обязаны работать вместе, следовательно, не связаны. Можно делать одно без другого.
Мне кажется, на размер бандла прежде всего влияют зависимости в большом количестве. А не enum.
Сколько будет в среднем проекте этих enum? 10? 20?
В разных областях конечно разные приоритеты, относительно того, когда следует жертвовать читаемостью кода ради некой оптимизации.
Но все перечисленные примеры мне кажутся с трудом обоснованными хоть для какого-нибудь проекта. Если хочется уменьшить размер, надо начать с исключения тяжелых зависимостей, как мне кажется.
Иными словами, предлагается не использовать возможности языка TypeScript, т.к. автор изначальной статьи не очень верит в first-class поддержку инструментами этого языка.
Выражу несогласие. TypeScript — один из достаточно хорошо продуманных и удобных инструментов, и поддерживается тем же бабелем он достаточно хорошо, чтобы использовать идиоматичные для многих языков конструкции, и не оглядываться на JS, которому отводится в этом случае роль IL, такого ассемблера своего рода.
Как мы не отказываемся от циклов for/foreach в серверных языках по причине лишь того, что в ассемблер или в IL они не транслируются "как есть", а выражаются через goto, так же и нет смысла отказываться от идиоматичных средств языка из-за особенностей трансляции в нижележащий "технический" язык исполнения.
Добрый день! Изучаю API Диска на предмет показа внутри своей веб-системы потокового видео с диска. Вижу, что ваш веб-клиент использует некое, судя по адресам, публичное API, например, yadi.sk/public-api-desktop/get-video-streams. Но не могу найти документацию на него. Есть ли она?
Или может быть все-таки есть некий способ сделать встраиваемый виджет для видео с Я.Диска?
эту проблему решил, добавив пользователя с именем SRV-1-1\Administrator в список пользователя в настройках Release Management.
теперь другая проблема: Deploy Agent не хочет подключаться к Server. причем установка Агента прошла успешно, видимо он сумел обратиться к Серверу в процессе этого.
Но на Клиенте функция Scan не работает, и добавление вручную Агента по IP тоже не приводит к его обнаружению (= статус Offline).
может потому, что я добавляю не доменным именем, а по IP? агент стоит на сервере, который не в домене. это вообще поддерживается?
Коллеги, а с кем можно пообщаться по поводу решения проблем при установке?
У меня Microsoft Deployment Agent не может подключиться к Release Management Server. Первый на сервере из живой площадки, не в домене, а второй в офисе, в домене.
Вся диагностическая информация от агента:
V, 2014/01/23, 01:22:49.324, Created Nt account for user Administrator
V, 2014/01/23, 01:22:49.324, Found Sid S-1-5-21-3719844311-4177430663-3684011079-500 for user Administrator
V, 2014/01/23, 01:22:49.324, Is Administrator network service account? False
V, 2014/01/23, 01:22:49.324, Created Nt account for user Administrator
V, 2014/01/23, 01:22:49.324, Found Sid S-1-5-21-3719844311-4177430663-3684011079-500 for user Administrator
V, 2014/01/23, 01:22:49.324, Is Administrator local system account? False
V, 2014/01/23, 01:22:49.324, Domain:
V, 2014/01/23, 01:22:49.324, Final UserName: SRV-1-1\Administrator.
V, 2014/01/23, 01:22:49.324, Loading account details for SRV-1-1\Administrator
V, 2014/01/23, 01:22:49.324, Is SRV-1-1\Administrator local machine account? True
I, 2014/01/23, 01:22:49.324, Normalized account is SRV-1-1\Administrator and Sid is S-1-5-21-3719844311-4177430663-3684011079-500
I, 2014/01/23, 01:22:49.340, Validating account to use as identity for Release Management Services...
I, 2014/01/23, 01:22:49.340, IsAdminAccount : Trying to determine if the account : SRV-1-1\Administrator is an admin on the local machine
I, 2014/01/23, 01:22:49.355, IsAdminAccount : Trying to determine if the account : SRV-1-1\Administrator is an admin on the local machine
I, 2014/01/23, 01:22:49.355, User SRV-1-1\Administrator is system, Admin
I, 2014/01/23, 01:22:49.355, Validated account to use as identity for Release Management Services.
I, 2014/01/23, 01:22:49.355, Validating Release Management Server for Team Foundation Server 2013...
E, 2014/01/23, 01:22:49.527, Received Exception : Microsoft.TeamFoundation.Release.CommonConfiguration.ConfigurationException: Failed to validate Release Management Server for Team Foundation Server 2013.
at Microsoft.TeamFoundation.Release.CommonConfiguration.DeployerConfigurationManager.ValidateServerUrl()
at Microsoft.TeamFoundation.Release.CommonConfiguration.DeployerConfigurationManager.ValidateAndConfigure(DeployerConfigUpdatePack updatePack, DelegateStatusUpdate statusListener)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
I, 2014/01/23, 01:22:49.527, Work completed for GetConfiguration() call : got out of turn error
E, 2014/01/23, 01:22:49.527, Failed to validate Release Management Server for Team Foundation Server 2013.
Конечно, я и не говорил, что это правильное определение. Я написал то, что должно было заинтересовать человека из мира Явы, не знакомого с такой концепцией вовсе. А уж с деталями он разберется, если откроет первую же статью по теме.
Так или иначе, но в одной из библиотек из той таблицы именно так и сделано. Есть метод Match, который обязывает обработать оба варианта, и только через него можно получить внутреннее значение. Честно, по-пацански по-монадически.
1. Как новичок, увидев вместо User MaybeUser я бы либо спросил у старшего, что это и как пользоваться, либо недюжинным мозговым усилием перевел слово Maybe на русский и догадался, что стоит сперва проверить на наличие значения.
2. А вот на кодревью скажут написать не так, как автор предложил, а что-то вроде такого:
если вам это так не нравится, то следует выбрать другой язык.
Абсолютно не следует, на то C# и мультипарадигменный язык.
Я бы хотел больше ФП-шности в нем, но не перехожу на F# или Haskell почему-то. Вам, возможно, арифметики указателей не хватает, и все же вы тоже не ушли в C.
Допустимы разные стили в рамках одного языка, только и всего. Вполне может быть, что для кого-то ваши «много классных штук» будут находиться в нерекомендуемом подмножестве языка. Как те же ref и out.
Переводить же все баги в разряд скрытых и трудноотлавливаемых — это как лгать самому себе.
Чистая правда, и ведь это именно NullReference таким и является, ведь он возникает отложенно (т.е. не там, где истинная причина, а много позже, когда столкнулись с последствиями), и как раз такие нехорошие ошибки мы заменили на явные и незамедлительно возникающие.
чем жестче будет падать система — тем лучше, быстрее починят
Это именно то, что у нас и происходило. Сразу ошибка «Объект не найден», сгенерированная кодом вида
return items.FirstMaybe(cond).OrElse(() => new ItemNotFoundException());
вместо NullReference где-то еще позже.
Так что ваш вывод о скрытых ошибках неверен, все наоборот — мы не прячем что-либо, а делаем еще одну неявную вещь — явной. Так что куча ошибок была, и была быстро исправлена, т.к. это были форсированные исключения, бросаемые очень близко к самой точке возникновения проблемы.
Как автор изначальной статьи, чувствую себя должным ответить, хотя по частям все эти мысли уже изложены выше другими участниками.
1. Автор приводит несколько, назовем их так, странные реализации GetItem, неявно постулируя, что они вытекают из первичной статьи. Однако же, они из нее ничуть не следуют.
Из нее может следовать, например, вот такая реализация, гарантирующая либо объект, либо исключение:
public Item GetItem(int itemId)
{
return dataAccessor
.getItemById(itemId)
.ToMaybe()
.OrElse(() => new ItemNotFound(itemId));
}
Либо такая, явно декларирующая возможность неудачного поиска, и трактующая его как нормальное, штатное поведение:
public Maybe<Item> FindItem(int itemId) // а Get выше тогда должен реализовываться через этот Find для устранения дублирования
{
return dataAccessor.getItemById(itemId).ToMaybe();
}
2.
При этом в одном из примеров он использует контракты, что противоречит их принципам.
При этом «противоречие принципам» автор иллюстрирует якобы необходимостью вставить в сторожевое условие сам код метода:
Что бы достать объект из репозитория, нужно сначала вытащить объект из репозитория.
Но если мы посмотрим на GetItem из п.1 моего комментария, то видим, что туда нужно только вставить Contract.Ensures(Contract.Result() != null); и более ничего; никакого коллапса вселенной бесконечной рекурсии это не вызывает.
3.
Правда в том, что никто не может гарантировать существование объекта в репозитории.
Я уже писал, что именно репозитории тут не специфичны. Но если в каком-то конкретном случае правда именно в этом (что объекта где-то может быть), я вовсе не предлагаю пытаться гарантировать наличие объекта, а предлагаю явно выразить эту правду, вернув Maybe.
4.
Я перефразирую: nullable reference. Масло масляное
Только потому кажется «масляным», что в виду ошибки проектирования языка классы в Algol C# по умолчанию снабжены значением null.
Anthony Hoare
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W)…
Если старичок Хоар покажется слишком далеким от нашего времени, вот цитата из Барта Де Смета, для .NET человека «изнутри», книга C# Unleashed, одна из Must-Read по классификации замечательного SergeyT:
Цитирую врезку из этой книги под характерным названием «Жизнь без null»
Давайте явно уясним одну вещь: (a) возможность/невозможность принимать значение null и (b) различие между значимыми и ссылочными типами — это ((a) vs (b)) ортогональные (независимые) свойства и это правильно. Было бы хорошо, если бы любой тип мог явно задекларировать, поддерживает ли он значение null, или нет.
И далее по тексту Барт говорит, что проектировщики C# не могли сделать эту ортогональность полной, т.е. в классах нет возможности «отключить null», и это вызвано лишь причинами совместимости. Например, в экспериментальном Spec# (где можно не думать так сильно о совместимости) такая возможность есть.
И раз современные средства позволяют в некотором локальном пространстве (проекте) ее исправить, то странно говорить о том, что это неверный подход. Что не мешает ему быть неоправданным в конкретном проекте по тысяче разных причин.
5.
Что мешает обратится к содержимому объекту без этой проверки? Можно точно так-же безалаберно не проверить на null через неравенство.
Я считаю, что вероятность первого много ниже, чем вероятность второго. Чтобы обратиться к содержимому Maybe без проверки, нужно совершить явное действие — добавить «.Value». Чтобы не проверить на null делать не нужно ничего, это уже сделано :).
Спотыкание об это «.Value» — это вроде как если бы у программиста был ангел-хранитель, который при каждом случае, когда тот написал GetSome().DoStuff(), волшебным образом смотрел бы в исходник GetSome(), и при необходимости стучал бы его по плечу и говорил: «А кстати, там может быть null».
Замечу, что как раз невозможность случайно игнорировать Maybe здорово стимулирует к тому, чтобы проектировать систему с минимальным количеством необязательных возвращаемых значений. И оказывается, что далеко не так часто нужны nullable-классы, как это кажется на первый взгляд. Они нужны приблизительно так же часто, как nullable-структуры. Иногда.
6. Для аргументирования вредности подхода автор приводит код:
public Maybe<Item> SomeMethod()
{
var mbItem = GetMbItem();
if(mbItem.HasValue)
{
var item = mbItem.Value;
ModifyItem(ref item);
}
return mbItem;
}
Во-первых, вполне явная ошибка: изменяем одну переменную, возвращаем другую, чего хорошего тут ждать, непонятно.
Однако, в духе Maybe, этот код пишется совсем иначе (учитывая, что ref и out использовать без крайней необходимости не следует, т.к. это ломает возможности функционального программирования):
public Maybe<Item> SomeMethod()
{
return GetMbItem().Select(ModifyItem);
}
где ModifyItem имеет вид Item ModifyItem(Item item){...}
Вполне могу согласиться с таким подходом, лишь бы команда его принимала и использовала единоообразно.
Хотя, при желании, вызовы библиотек прекрасно оборачиваются ToMaybe, об использовании неинициализированных переменных и полей предупреждает компилятор или решарпер, а в алгоритмах вполне можно как обходиться без null, так и «разрешить» его локальное использование особым способом (зависящим от того, каким методом null был запрещен; например, специальным комментарием).
Я так понял, что вы имеете в виду шаблон Null Object. Это вполне хорошее решение, когда оно на своем месте. Однако, на мой взгляд, на роль универсального избавителя от null оно не подходит. Этот шаблон относится к моделированию предметной области: если у нас есть семейство объектов (например, разные типы Начислений в финансовом приложении), и для них можно (для унификации обработки) говорить также об Отсутствующем Начислении (если это имеет смысл с точки зрения той модели, в которой мыслят пользователи и проектировщики приложения), то это хорошее место для применения Null Object.
Однако, если у меня есть коллекция users и мне нужно сделать следующее:
var defaultAdmin = ...;
var admin = users.FirstMaybe(u => u.IsAdmin).OrElse(defaultAdmin);
То тут вводить NullUser, на мой взгляд, неуместно, так как он не будет представлять никакую существенную концепцию в модели предметной области.
Что же касается возможности вызвать maybe.Value при отсутствии значения, она, хоть и приведет к исключению, все же является явной операцией. Вы прицеливаетесь и четко стреляете себе в ногу, сие есть ваше неотъемлемое право. Мы лишь гарантируем, чтобы пистолет не выстрелил без нажатия на курок :)
Он не писал, что нельзя совмещать, вы неверно прочли. Он написал, что они не обязаны работать вместе, следовательно, не связаны. Можно делать одно без другого.
Спасибо за статью, рад что проект живёт. Я в свое время приложил руку к разработке этого монолита :-)
Хотел спросить, тк не очень понял из статьи, на какие всё-таки конкретно микросервисы вы порезали его?
Мне кажется, на размер бандла прежде всего влияют зависимости в большом количестве. А не enum.
Сколько будет в среднем проекте этих enum? 10? 20?
В разных областях конечно разные приоритеты, относительно того, когда следует жертвовать читаемостью кода ради некой оптимизации.
Но все перечисленные примеры мне кажутся с трудом обоснованными хоть для какого-нибудь проекта. Если хочется уменьшить размер, надо начать с исключения тяжелых зависимостей, как мне кажется.
Иными словами, предлагается не использовать возможности языка TypeScript, т.к. автор изначальной статьи не очень верит в first-class поддержку инструментами этого языка.
Выражу несогласие. TypeScript — один из достаточно хорошо продуманных и удобных инструментов, и поддерживается тем же бабелем он достаточно хорошо, чтобы использовать идиоматичные для многих языков конструкции, и не оглядываться на JS, которому отводится в этом случае роль IL, такого ассемблера своего рода.
Как мы не отказываемся от циклов for/foreach в серверных языках по причине лишь того, что в ассемблер или в IL они не транслируются "как есть", а выражаются через goto, так же и нет смысла отказываться от идиоматичных средств языка из-за особенностей трансляции в нижележащий "технический" язык исполнения.
Или может быть все-таки есть некий способ сделать встраиваемый виджет для видео с Я.Диска?
теперь другая проблема: Deploy Agent не хочет подключаться к Server. причем установка Агента прошла успешно, видимо он сумел обратиться к Серверу в процессе этого.
Но на Клиенте функция Scan не работает, и добавление вручную Агента по IP тоже не приводит к его обнаружению (= статус Offline).
может потому, что я добавляю не доменным именем, а по IP? агент стоит на сервере, который не в домене. это вообще поддерживается?
У меня Microsoft Deployment Agent не может подключиться к Release Management Server. Первый на сервере из живой площадки, не в домене, а второй в офисе, в домене.
Вся диагностическая информация от агента:
по-пацанскипо-монадически.2. А вот на кодревью скажут написать не так, как автор предложил, а что-то вроде такого:
Абсолютно не следует, на то C# и мультипарадигменный язык.
Я бы хотел больше ФП-шности в нем, но не перехожу на F# или Haskell почему-то. Вам, возможно, арифметики указателей не хватает, и все же вы тоже не ушли в C.
Допустимы разные стили в рамках одного языка, только и всего. Вполне может быть, что для кого-то ваши «много классных штук» будут находиться в нерекомендуемом подмножестве языка. Как те же ref и out.
Чистая правда, и ведь это именно NullReference таким и является, ведь он возникает отложенно (т.е. не там, где истинная причина, а много позже, когда столкнулись с последствиями), и как раз такие нехорошие ошибки мы заменили на явные и незамедлительно возникающие.
Это именно то, что у нас и происходило. Сразу ошибка «Объект не найден», сгенерированная кодом вида
вместо NullReference где-то еще позже.
Так что ваш вывод о скрытых ошибках неверен, все наоборот — мы не прячем что-либо, а делаем еще одну неявную вещь — явной. Так что куча ошибок была, и была быстро исправлена, т.к. это были форсированные исключения, бросаемые очень близко к самой точке возникновения проблемы.
1. Автор приводит несколько, назовем их так, странные реализации GetItem, неявно постулируя, что они вытекают из первичной статьи. Однако же, они из нее ничуть не следуют.
Из нее может следовать, например, вот такая реализация, гарантирующая либо объект, либо исключение:
Либо такая, явно декларирующая возможность неудачного поиска, и трактующая его как нормальное, штатное поведение:
2. При этом «противоречие принципам» автор иллюстрирует якобы необходимостью вставить в сторожевое условие сам код метода:
Но если мы посмотрим на GetItem из п.1 моего комментария, то видим, что туда нужно только вставить Contract.Ensures(Contract.Result() != null); и более ничего; никакого
коллапса вселеннойбесконечной рекурсии это не вызывает.3.
Я уже писал, что именно репозитории тут не специфичны. Но если в каком-то конкретном случае правда именно в этом (что объекта где-то может быть), я вовсе не предлагаю пытаться гарантировать наличие объекта, а предлагаю явно выразить эту правду, вернув Maybe.
4.
Только потому кажется «масляным», что в виду ошибки проектирования языка классы в
AlgolC# по умолчанию снабжены значением null.Anthony Hoare
посмотреть на человека-легенду
Если старичок Хоар покажется слишком далеким от нашего времени, вот цитата из Барта Де Смета, для .NET человека «изнутри», книга C# Unleashed, одна из Must-Read по классификации замечательного SergeyT:
Цитирую врезку из этой книги под характерным названием «Жизнь без null»
И далее по тексту Барт говорит, что проектировщики C# не могли сделать эту ортогональность полной, т.е. в классах нет возможности «отключить null», и это вызвано лишь причинами совместимости. Например, в экспериментальном Spec# (где можно не думать так сильно о совместимости) такая возможность есть.
И раз современные средства позволяют в некотором локальном пространстве (проекте) ее исправить, то странно говорить о том, что это неверный подход. Что не мешает ему быть неоправданным в конкретном проекте по тысяче разных причин.
5.
Я считаю, что вероятность первого много ниже, чем вероятность второго. Чтобы обратиться к содержимому Maybe без проверки, нужно совершить явное действие — добавить «.Value». Чтобы не проверить на null делать не нужно ничего, это уже сделано :).
Спотыкание об это «.Value» — это вроде как если бы у программиста был ангел-хранитель, который при каждом случае, когда тот написал GetSome().DoStuff(), волшебным образом смотрел бы в исходник GetSome(), и при необходимости стучал бы его по плечу и говорил: «А кстати, там может быть null».
Замечу, что как раз невозможность случайно игнорировать Maybe здорово стимулирует к тому, чтобы проектировать систему с минимальным количеством необязательных возвращаемых значений. И оказывается, что далеко не так часто нужны nullable-классы, как это кажется на первый взгляд. Они нужны приблизительно так же часто, как nullable-структуры. Иногда.
6. Для аргументирования вредности подхода автор приводит код:
Во-первых, вполне явная ошибка: изменяем одну переменную, возвращаем другую, чего хорошего тут ждать, непонятно.
Однако, в духе Maybe, этот код пишется совсем иначе (учитывая, что ref и out использовать без крайней необходимости не следует, т.к. это ломает возможности функционального программирования):
где ModifyItem имеет вид Item ModifyItem(Item item){...}
Или, если очень приспичило, даже с ref:
7. Что же касается тезиса готов принять даже более широкий тезис, например, такой: «нужно быть внимательным».
И да удастся это нам всем :)
Хотя, при желании, вызовы библиотек прекрасно оборачиваются ToMaybe, об использовании неинициализированных переменных и полей предупреждает компилятор или решарпер, а в алгоритмах вполне можно как обходиться без null, так и «разрешить» его локальное использование особым способом (зависящим от того, каким методом null был запрещен; например, специальным комментарием).
ваш первый тезис становится неверным.
Однако, если у меня есть коллекция users и мне нужно сделать следующее:
То тут вводить NullUser, на мой взгляд, неуместно, так как он не будет представлять никакую существенную концепцию в модели предметной области.
Что же касается возможности вызвать maybe.Value при отсутствии значения, она, хоть и приведет к исключению, все же является явной операцией. Вы прицеливаетесь и четко стреляете себе в ногу, сие есть ваше неотъемлемое право. Мы лишь гарантируем, чтобы пистолет не выстрелил без нажатия на курок :)