Re[12]: Проект утилитной библиотечки
От: IT Россия linq2db.com
Дата: 18.03.16 16:38
Оценка:
Здравствуйте, rameel, Вы писали:

R>Нельзя, не скомпилируется


Почему это? IsNullOrEmpty компилируется а Format нет. У меня это кругом в linq2db, заменил на Format всё отлично компилируется.
Если нам не помогут, то мы тоже никого не пощадим.
Re[13]: Проект утилитной библиотечки
От: rameel https://github.com/rsdn/CodeJam
Дата: 18.03.16 16:47
Оценка:
Здравствуйте, IT, Вы писали:

R>>Нельзя, не скомпилируется


IT>Почему это? IsNullOrEmpty компилируется а Format нет. У меня это кругом в linq2db, заменил на Format всё отлично компилируется.


Будет ошибка, если первый параметр строка. Компилятор в этом случае предпочитает смотреть на string.Format(string, params object[])
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[5]: Проект утилитной библиотечки
От: DreamMaker  
Дата: 18.03.16 17:28
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Чего то ничего не придумывается. Есть идеи?


KrymNash.NET


ну а если серьезно, в принципе, это интересно, но боюсь у каждого свои привычки и свои велосипеды.

мне вот нравятся string extension strTill и strAfter, которые возвращают подстроку до указанного паттерна или после.
еще генерация нормально распреденных случайных чисел.

public static void xmlSerialize<T>(T obj, string fileName)
public static void xmlDeserialize<T>(string fileName, out T obj)
то же для binary.

сериализируемый в XML dictionary

static public T getAssemblyAttribute<T>() where T : Attribute

averageOrZero, которая нуль на пустой последовательности возвращает а не исключениями кидается

standard deviation

в юниксное и из юниксного времени (в 4.6 вроде штатное сделали?)

всякие время в EST и американские Bank Holidays полагаю только мне нужны?
.isWeekend для даты вполне полезен всем, проверка на субботу или воскресенье

ну это на вскидку.
In P=NP we trust.
Re[6]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.03.16 20:51
Оценка:
Здравствуйте, DreamMaker, Вы писали:

DM>ну а если серьезно, в принципе, это интересно, но боюсь у каждого свои привычки и свои велосипеды.


Ничего страшного. Нормальный программист свои привычки меняет, особенно если особого рационала в них нет. А упертые все равно свои велосипеды будут изобретать для несложных вещей.

DM>мне вот нравятся string extension strTill и strAfter, которые возвращают подстроку до указанного паттерна или после.


Полезная вещь. Родной Substring поддерживает только два сценария нормально — произвольный кусок из середины и произвольный кусок с начала. Когда нужно с конца код превращается в кракозябу. А руки написал хелпер как обычно не доходят, ибо мелкий и проще забить.

DM>еще генерация нормально распреденных случайных чисел.


Нормально в матсмысле, т.е. по Гауссу, или просто равномерное с хорошим качеством?

DM> public static void xmlSerialize<T>(T obj, string fileName)

DM> public static void xmlDeserialize<T>(string fileName, out T obj)
DM>то же для binary.

А тут какой смысл?

DM>сериализируемый в XML dictionary


Сериализуемость в XML понятие растяжимое. XmlDataSerializer, к примеру, словари сериализует искаропки.

DM> static public T getAssemblyAttribute<T>() where T : Attribute


Это в роадмапе уже есть.

DM>averageOrZero, которая нуль на пустой последовательности возвращает а не исключениями кидается


Это вроде уже реализовано даже.

DM>всякие время в EST и американские Bank Holidays полагаю только мне нужны?


Время в EST несложно и так посчитать, а праздники в код хардкодить — сомнительная практика. Я понимаю что не РФ, где каждый год выпускаюьт указ, но все таки изменения могут быть.

DM>.isWeekend для даты вполне полезен всем, проверка на субботу или воскресенье


Викэнд зависит от культуры, так что корректная реализация такого дело очень нетривиальное. МС, к сожалению, не озаботилась добавлением соответствующего функционала в календари.

DM>ну это на вскидку.


Ну вскидывай дальше.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[11]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.03.16 21:04
Оценка:
Здравствуйте, IT, Вы писали:

IT>Если честно, то я почти никогда не объявляю форматную строку отдельно от string.Format. Поэтому выглядеть это будет так:


IT>
IT>return "Hello, {0}".Args(wellKnownNames[0]);
IT>


Для константного формата и 6 шарпа уже не надо так делать. Надо так:

return $"Hello, {wellKnownNames[0]}";


А вот если не константа ...

IT>Это проблема не только этого метода, а любого расширения. Я сам хотел поднять эту тему. Сейчас у нас все расширения находяться в основном пространстве имён, что автоматически добавляет их все.


У меня лично много опыта использования экстеншенов на весьма крупных проектах и большом количестве этих экстеншенов. И на практике оказалось, что никаких проблем нет даже когда все экстеншены находятся в пространстве имен прикладного кода. Тип аргумента обычно достаточно селективен, особенно если не навешивать расширения на object.
Да посмотреть даже на сам Fx. Enumerable цепляется к очень распространенному типу, содержит очень большое количество расширений к нему (в фреймворке, наверное, рекордно большое), находится в том же самом неймспейсе, что и все коллекции, т.е. гарантированно попадает в любой код. Получается worst сценарий. Таки и что? Да ничего, все вполне нормально и удобно.
С другой стороны, когда у нас все в одном пространстве имен, это добавляет discoverability, которая при разнесении расширений по куче неймспейсов падает стремительным домкратом до уровня обычных статических методов, за что их не попинал только ленивый любитель С++ и свободных функций. И вот это уже реальная, а не теоретическая проблема.

IT>Как минимум я бы перенёс все расширения куда-нибудь в CodeJam.Extensions.


И что это даст? Лишний юсинг в прикладном коде?

IT> И заодно перетасовал бы файлы в проекте. Соответсвие папок пространсвам имён тоже вроде пока никто не отменял.


Очень неудобно. Если у меня классов много — будут неструктурированные длинные списки, если класс только один — дурацкая ситуация папки с одним файлом. ИМХО ну его нафик, средств навигации даже голой студии вполне достаточно, чтобы не искать классы по структуре папок. Я уж не говорю про решарпер.
Пространства имен предназначены для одного — обеспечения отсутствия конфликта имен. Попытка привязать к ним какую то еще ответственность — отличный способ прострелить себе ногу.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[12]: Проект утилитной библиотечки
От: Evgeny.Panasyuk Россия  
Дата: 18.03.16 21:22
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Оставшийся 1% это бинарный поиск, но там вообще пофик какая сортировка, лишь бы была стабильной.


В каком смысле стабильной? Для бинарного поиска и нестабильная подходит.
Re: Проект утилитной библиотечки
От: RushDevion Россия  
Дата: 18.03.16 22:19
Оценка:
Добавлю еще пару методов для строк:
string.CutStart(this str, string prefix)
string.CutEnd(this str, string suffix)

И по-поводу сборки в nuget-пакет есть вот какие соображения.
При наличии specific framework (WinForms/WPF, WCF, ASP.NET MVC, System.XML и т.п.)-ориентированного кода будут тянуться лишние зависимости, которые понятное дело не всем нужны.
Мы так пробовали и в итоге отказались от одного большого пакета с хелперами.
Сейчас пользуемся идеей, описанной в https://github.com/phatboyg/Internals.
Т.е. подключаем репозиторий как сабмодуль, в солюшене делаем собственную сборку MyCompany.MyProject.Internals,
накидываем туда нужные файлы через "Add as link", подключаем нужные либы. Так в каждый проект попадают только реально нужные хелперы.

Одно другого не отменяет, но, возможно, есть смысл упомянуть и о таком подходе где-нибудь в документации.
Re[2]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.03.16 22:43
Оценка:
Здравствуйте, RushDevion, Вы писали:

RD>Добавлю еще пару методов для строк:

RD>
RD>string.CutStart(this str, string prefix)
RD>string.CutEnd(this str, string suffix)
RD>


И что они должны делать?

RD>И по-поводу сборки в nuget-пакет есть вот какие соображения.

RD>При наличии specific framework (WinForms/WPF, WCF, ASP.NET MVC, System.XML и т.п.)-ориентированного кода будут тянуться лишние зависимости, которые понятное дело не всем нужны.

С самого начала было сказано — на пакеты делить по зависимостям. Но на текущем этапе разработка ведется только для полностью универсального кода, зависящего только от ядра фреймворка. Никаких WPF и ASP.NET. Чем, правда, System.Xml не угодил я не понял.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[3]: Проект утилитной библиотечки
От: RushDevion Россия  
Дата: 19.03.16 06:04
Оценка:
RD>>
RD>>string.CutStart(this str, string prefix)
RD>>string.CutEnd(this str, string suffix)
RD>>


AVK>И что они должны делать?

Откусывать от начала/конца строки заданную подстроку (если она там есть). Удобно при разборе строк использовать e.g.
  var str = @"SOMEDOMAIN\UserName@somedomain.com";
  var userName = str.CutStart(@"SOMEDOMAIN\").CutEnd("@somedomain.com");
  // Вместо 
  if (str.StartsWith(@"SOMEDOMAIN\")) str = str.Substring(@"SOMEDOMAIN\".Length);
  if (str.EndsWith("@somedomain.com") str = str.Substring(0, str.Length-"@somedomain.com".Length);

  // P.S. str.Replace(@"SOMEDOMAIN\", "").Replace("@somedomain.com", "") в общем случае не подойдет, т.к. заменит по всей строке


AVK> Чем, правда, System.Xml не угодил я не понял.

К слову пришлось. Я решарперовским "Remove unused library references" часто пользуюсь — не люблю, чтобы в солюшене были ссылки на неиспользуемые либы.
Re[4]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 19.03.16 10:25
Оценка:
Здравствуйте, RushDevion, Вы писали:

AVK>>И что они должны делать?

RD>Откусывать от начала/конца строки заданную подстроку (если она там есть). Удобно при разборе строк использовать e.g.

Так а при откусывании зачем префикс/суффикс? Типа сперва нужно проверить на совпадение или это такой извращенный способ передать длину откусываемого?

AVK>> Чем, правда, System.Xml не угодил я не понял.

RD>К слову пришлось. Я решарперовским "Remove unused library references" часто пользуюсь — не люблю, чтобы в солюшене были ссылки на неиспользуемые либы.

Не особо осмысленное занятие. Неиспользуемые сборки все равно не грузятся, даже если на них ссылка есть.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[5]: Проект утилитной библиотечки
От: RushDevion Россия  
Дата: 19.03.16 13:36
Оценка: +1
AVK>Так а при откусывании зачем префикс/суффикс? Типа сперва нужно проверить на совпадение или это такой извращенный способ передать длину откусываемого?
Да, проверить на совпадение, если совпало-откусить.
Наверное, название не очень удачное (просто я к нему привык, глаз замылился).
Это скорее аналоги TrimStart() и TrimEnd(), которые тримают подстроки, а не отдельные символы.
Хотя, с другой стороны "ababc".CutStart("ab") вернет "abc", а "ababc".TrimStart("ab") по идее должен вернуть только "c".
Re[6]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 19.03.16 23:10
Оценка:
Здравствуйте, RushDevion, Вы писали:

Добавил TrimPrefix/TrimSuffix. Тесты:
[TestCase("abc", null, ExpectedResult = "abc")]
[TestCase("abc", "", ExpectedResult = "abc")]
[TestCase("abc", "abcd", ExpectedResult = "abc")]
[TestCase("abc", "ab", ExpectedResult = "c")]
[TestCase("abc", "ac", ExpectedResult = "abc")]
[TestCase("abc", "abc", ExpectedResult = "")]
public string TrimPrefix(string str, string prefix) => str.TrimPrefix(prefix);

[TestCase("abc", null, ExpectedResult = "abc")]
[TestCase("abc", "", ExpectedResult = "abc")]
[TestCase("abc", "abcd", ExpectedResult = "abc")]
[TestCase("abc", "bc", ExpectedResult = "a")]
[TestCase("abc", "ac", ExpectedResult = "abc")]
[TestCase("abc", "abc", ExpectedResult = "")]
public string TrimSuffix(string str, string suffix) => str.TrimSuffix(suffix);
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[12]: Проект утилитной библиотечки
От: IT Россия linq2db.com
Дата: 20.03.16 18:40
Оценка: +1
Здравствуйте, AndrewVK, Вы писали:

AVK>Для константного формата и 6 шарпа уже не надо так делать. Надо так:


Это когда ещё будет. Если помнишь, народ тут просил поддержку 4-го FW, а ты про 6-й решарпер.

IT>>Это проблема не только этого метода, а любого расширения. Я сам хотел поднять эту тему. Сейчас у нас все расширения находяться в основном пространстве имён, что автоматически добавляет их все.


AVK>У меня лично много опыта использования экстеншенов на весьма крупных проектах и большом количестве этих экстеншенов. И на практике оказалось, что никаких проблем нет даже когда все экстеншены находятся в пространстве имен прикладного кода. Тип аргумента обычно достаточно селективен, особенно если не навешивать расширения на object.

AVK>Да посмотреть даже на сам Fx. Enumerable цепляется к очень распространенному типу, содержит очень большое количество расширений к нему (в фреймворке, наверное, рекордно большое), находится в том же самом неймспейсе, что и все коллекции, т.е. гарантированно попадает в любой код. Получается worst сценарий. Таки и что? Да ничего, все вполне нормально и удобно.

Т.е. всё-таки не в корневом, а в том к чему оно относится.

AVK>С другой стороны, когда у нас все в одном пространстве имен, это добавляет discoverability, которая при разнесении расширений по куче неймспейсов падает стремительным домкратом до уровня обычных статических методов, за что их не попинал только ленивый любитель С++ и свободных функций. И вот это уже реальная, а не теоретическая проблема.


IT>>Как минимум я бы перенёс все расширения куда-нибудь в CodeJam.Extensions.


AVK>И что это даст? Лишний юсинг в прикладном коде?


У меня лично много опыта использования экстеншенов на весьма крупных проектах и большом количестве этих экстеншенов. И на практике оказалось, что с лишним юзингом нет никаких проблем. Но да фиг с ним. Дело не в нём, а в структуре проекта.

IT>> И заодно перетасовал бы файлы в проекте. Соответсвие папок пространсвам имён тоже вроде пока никто не отменял.


AVK>Очень неудобно.


Очень удобно.

AVK>Если у меня классов много — будут неструктурированные длинные списки, если класс только один — дурацкая ситуация папки с одним файлом. ИМХО ну его нафик, средств навигации даже голой студии вполне достаточно, чтобы не искать классы по структуре папок. Я уж не говорю про решарпер.


Навигация дело десятое, хотя и она для кого-то может оказаться важна.

AVK>Пространства имен предназначены для одного — обеспечения отсутствия конфликта имен. Попытка привязать к ним какую то еще ответственность — отличный способ прострелить себе ногу.


Тогда по твоей логике все классы фреймворка нужно было поместить в System. Конфликтов имён там почти нет, а там где они есть можно всегда создать неймспейс, при этом особо не париться и называть их по порядку A, B, C.

В общем, я даже как-то теряюсь от твоей аргументации. Неймспейсы лично для меня всегда были не средством разруливания конфликтов имён, а преждес всего механизмом организации кода проекта, средством устранения свалки всего в одном месте, как ты здесь предлагаешь. Соотвествие папок неймспейсам — это вообще-то соглашение индустриального уровня и уже давно ни у кого не вызывает вопросов. Сейчас же, уверен, у большинства из тех, кто решит посмотреть на код библиотеки, первым делом возникнет сомнение в профессиональном уровне разработчиков, т.к. возникнет ощущение, что тут собрались не профи, а орлята учатся летать.

Для хелперных классов давно уже существует очень простое правило — их следует помещать в неймспейсы с именем неймспейса того класса, для котого делается хелпер. Так для типов String, Type это может быть корневой неймспейс. Для коллекций Collection, для расширений Linq — соответственно Linq. Не думаю, что таких неймспейсов будет много и что это вызовет какие-то сложности при их использовании. Но зато библиотека станет лучше организована, более логична и предсказуема.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Проект утилитной библиотечки
От: dr. Acula Украина  
Дата: 20.03.16 18:44
Оценка:
V>Natasha, Romashka
Vovka, Dimka, WladimirWladimirovitsch
Re[7]: Проект утилитной библиотечки
От: IT Россия linq2db.com
Дата: 20.03.16 18:46
Оценка:
Здравствуйте, AndrewVK, Вы писали:

А чем TrimStart, TrimEnd не понравилось?
Если нам не помогут, то мы тоже никого не пощадим.
Re[13]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.03.16 19:44
Оценка:
Здравствуйте, IT, Вы писали:

AVK>>Да посмотреть даже на сам Fx. Enumerable цепляется к очень распространенному типу, содержит очень большое количество расширений к нему (в фреймворке, наверное, рекордно большое), находится в том же самом неймспейсе, что и все коллекции, т.е. гарантированно попадает в любой код. Получается worst сценарий. Таки и что? Да ничего, все вполне нормально и удобно.


IT>Т.е. всё-таки не в корневом, а в том к чему оно относится.


Оно прежде всего в томже неймспейсе, что и this аругмент, а не в System.Collections.Generic.Extensions. Я вообще не припомню в фреймворке случая чтобы экстеншены были в отдельном неймспейсе.

IT>У меня лично много опыта использования экстеншенов на весьма крупных проектах и большом количестве этих экстеншенов. И на практике оказалось, что с лишним юзингом нет никаких проблем.


Это лишнее действие, лишняя строка кода.

AVK>>Если у меня классов много — будут неструктурированные длинные списки, если класс только один — дурацкая ситуация папки с одним файлом. ИМХО ну его нафик, средств навигации даже голой студии вполне достаточно, чтобы не искать классы по структуре папок. Я уж не говорю про решарпер.

IT>Навигация дело десятое, хотя и она для кого-то может оказаться важна.

Тогда зачем вообще соответствие неймспейсов и папок?

AVK>>Пространства имен предназначены для одного — обеспечения отсутствия конфликта имен. Попытка привязать к ним какую то еще ответственность — отличный способ прострелить себе ногу.

IT>Тогда по твоей логике все классы фреймворка нужно было поместить в System.

Нет.

IT> Конфликтов имён там почти нет


Там — нет. А вот в прикладном коде, если бы весь фреймворк был в одном неймспейсе, было бы много просто в силу объема фреймворка. У нас же таких объемов не будет никогда.
При этом, если есть каой то крупный и обособленный кусок — абсолютно согласен ч тем чтобы вытащить его в отдельный неймспейс. См. тот же парсер командной строки — там куча специфичных классов. Поэтому я его и вынес в CodeJam.CmdLine.
А вот выносить в отдельный неймспейс 2-3 функции, или объединять совершенно разнородные методы просто потому что они extension — это какой то процесс ради процесса. К примеру, есть у нас класс Disposable и класс DisposableExtensions. Их надо по разным неймспейсам разнести или как?
Резюмируя — предлагаю вводить новый неймспейс тогда, когда есть хотя бы с десяток классов, тесно и однозначно чем то объединенных. А когда там 2-3 класса на всю тематику, то нефик и сиськи мять, пусть все лежит в корневом.

IT>В общем, я даже как-то теряюсь от твоей аргументации. Неймспейсы лично для меня всегда были не средством разруливания конфликтов имён, а преждес всего механизмом организации кода проекта, средством устранения свалки всего в одном месте, как ты здесь предлагаешь.


А чем тебя в этом качестве не устраивают банальные папки?

IT> Соотвествие папок неймспейсам — это вообще-то соглашение индустриального уровня и уже давно ни у кого не вызывает вопросов.


Регулярно вижу обратное.

IT> Сейчас же, уверен, у большинства из тех, кто решит посмотреть на код библиотеки, первым делом возникнет сомнение в профессиональном уровне разработчиков, т.к. возникнет ощущение, что тут собрались не профи, а орлята учатся летать.


Ага, вот тут еще орлята-ламеры, к примеру, собрались — https://github.com/dotnet/roslyn/tree/master/src/Compilers/Server/PortableServer
Всегда знал что с розлином что то не так.
Ребята из решапрера, кстати, поначалу тоже так как ты считали, но быстро от иллюзий избавились. И сейчас в решарпере связь эта настраиваемая, а не жесткая, а относительно свежие версии еще и научились смотреть на соседние файлики, а не тупо на структуру каталогов.

IT>Для хелперных классов давно уже существует очень простое правило — их следует помещать в неймспейсы с именем неймспейса того класса, для котого делается хелпер.


Т.е. помещаем DisposableExtensions в System?

IT> Так для типов String, Type это может быть корневой неймспейс. Для коллекций Collection, для расширений Linq — соответственно Linq.


Но у IEnumerable неймспейс не Linq, а System.Collections.Generic. У коллекций же их вообще несколько. Как то все очень расплывчато получается.

IT> Не думаю, что таких неймспейсов будет много и что это вызовет какие-то сложности при их использовании.


Это прежде всего лишние сущности, лишние юзинги и снижение discoverability, хз как это по русски.

IT> Но зато библиотека станет лучше организована,


Лучше ли?

IT> более логична и предсказуема.


Обоснуй.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.03.16 19:45
Оценка:
Здравствуйте, IT, Вы писали:

IT>А чем TrimStart, TrimEnd не понравилось?


Потому что такие методы у string уже есть и делают они несколько иное.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[14]: Проект утилитной библиотечки
От: IT Россия linq2db.com
Дата: 20.03.16 21:37
Оценка:
Здравствуйте, AndrewVK, Вы писали:

IT>>Т.е. всё-таки не в корневом, а в том к чему оно относится.


AVK>Оно прежде всего в томже неймспейсе, что и this аругмент, а не в System.Collections.Generic.Extensions. Я вообще не припомню в фреймворке случая чтобы экстеншены были в отдельном неймспейсе.


Extensions имеет смысл, если их туда собрать все. А так следует всё помещать в соответствующие неймспейсы.

IT>>У меня лично много опыта использования экстеншенов на весьма крупных проектах и большом количестве этих экстеншенов. И на практике оказалось, что с лишним юзингом нет никаких проблем.

AVK>Это лишнее действие, лишняя строка кода.

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

AVK>Тогда зачем вообще соответствие неймспейсов и папок?


Затем, что это предсказуемо.

AVK>Там — нет. А вот в прикладном коде, если бы весь фреймворк был в одном неймспейсе, было бы много просто в силу объема фреймворка.


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

AVK>А вот выносить в отдельный неймспейс 2-3 функции, или объединять совершенно разнородные методы просто потому что они extension — это какой то процесс ради процесса. К примеру, есть у нас класс Disposable и класс DisposableExtensions. Их надо по разным неймспейсам разнести или как?


Какая разница сколько там функций? Да хоть одна. Не вижу никаких проблем. Зато искать будет легко и просто.

AVK>Резюмируя — предлагаю вводить новый неймспейс тогда, когда есть хотя бы с десяток классов, тесно и однозначно чем то объединенных. А когда там 2-3 класса на всю тематику, то нефик и сиськи мять, пусть все лежит в корневом.


А если потом к твоим 2-3-м классам добавиться ещё 7-8, то ты их перенесёшь в отдельный неймспейс? Мы тут делаем библиотеку общего назначения, не забыл? С таким подходом у неё нет будущего.

AVK>А чем тебя в этом качестве не устраивают банальные папки?


Навигация в решарпере — это хорошо. Но тот, кто поставит нугет и будет пользоваться этой библиотекой вряд ли будет качать её исходники и включать её в свой проект ради решарпера. Когда мне нужно посмотреть код в какой-то открытой библиотеке и она находится на гитхабе, то я иду туда и ищу нужный класс ориентируясь прежде всего по неймспейсам. Ты эту возможность народу сразу закрываешь, при этом вся твоя аргументация базируется исключительно на вкусовщине.

IT>> Соотвествие папок неймспейсам — это вообще-то соглашение индустриального уровня и уже давно ни у кого не вызывает вопросов.

AVK>Регулярно вижу обратное.

Мне тоже доводилось такое видеть. Как правило в таких прокетах чёрт ногу сломит. Давай с самого начала и здесь устроим подобный бардак?

IT>> Сейчас же, уверен, у большинства из тех, кто решит посмотреть на код библиотеки, первым делом возникнет сомнение в профессиональном уровне разработчиков, т.к. возникнет ощущение, что тут собрались не профи, а орлята учатся летать.


AVK>Ага, вот тут еще орлята-ламеры, к примеру, собрались — https://github.com/dotnet/roslyn/tree/master/src/Compilers/Server/PortableServer

AVK>Всегда знал что с розлином что то не так.

И что там не так?

AVK>Ребята из решапрера, кстати, поначалу тоже так как ты считали, но быстро от иллюзий избавились. И сейчас в решарпере связь эта настраиваемая, а не жесткая, а относительно свежие версии еще и научились смотреть на соседние файлики, а не тупо на структуру каталогов.


Ещё раз.

1. Мы делаем не конечный продукт на который никогда не появлится не одного референса, а библиотеку общего назначения. Т.е. требования к ней принципиально другие, чем к тому же Решарперу или мелкой утилитке из Рослина.
2. Из каждого правила есть исключения лишь подтверждающие правила. Если есть нормальное логическое обоснование, а не просто личные предпочтения, то всегда можно сделать по-другому. Но не надо это сразу превращать в правило.

IT>>Для хелперных классов давно уже существует очень простое правило — их следует помещать в неймспейсы с именем неймспейса того класса, для котого делается хелпер.

AVK>Т.е. помещаем DisposableExtensions в System?

В CodeJam.
Всё касающееся коллекций в CodeJam.Collections.
Linq в CodeJam.Linq.

И так далее по аналогии. Т.е. вместо System ставим CodeJam. Ещё я бы не стал всё, касающееся коллекций запихивать в соостветствующие неймспейсы. Collections вполне достаточно.

IT>> Так для типов String, Type это может быть корневой неймспейс. Для коллекций Collection, для расширений Linq — соответственно Linq.


AVK>Но у IEnumerable неймспейс не Linq, а System.Collections.Generic. У коллекций же их вообще несколько. Как то все очень расплывчато получается.


Это как раз то самое исключение.

IT>> Не думаю, что таких неймспейсов будет много и что это вызовет какие-то сложности при их использовании.

AVK>Это прежде всего лишние сущности, лишние юзинги и снижение discoverability, хз как это по русски.

Ты же решарпером пользуещься, там это без проблем.

IT>> более логична и предсказуема.

AVK>Обоснуй.

Размещая расширения в произвольных папках ты только путаешь тех, кто будет изучать код библиотеки. Открыв проект и увидев папку String первое, что мне придёт в голову, что есть такой namespace CodeJam.String. Или наоборот, если я захочу посмотреть на гитхабе код StringExtensions.Substring, то искать я его буду в корне и очень сильно удивлюсь не найдя его там. И придётся мне с матом бродить по всем папкам. Что касается строк, то проявив смекалку я может быть быстро дойду до папки String, но вот с тем же CharExtensions.IsDigit уже могут быть проблемы.

Далее. Как я уже говорил, критерий выноса кода в отдельный неймспейс по количеству файлов приведёт либо к бардаку, либо к ломке совместимости в будущем, т.е. ни к чему хорошему.

Наличие открытых неймспейсов в коде — это не лишная, а очень даже полезная информация, которая лично мне сразу даёт представление с чем в данном файле придётся столкнуться. Поэтому увидев в коде using CodeJam.Collections; мне уже будет примерно понятно с чем я тут буду иметь дело.
Если нам не помогут, то мы тоже никого не пощадим.
Re[15]: Проект утилитной библиотечки
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.03.16 23:09
Оценка:
Здравствуйте, IT, Вы писали:

AVK>>Оно прежде всего в томже неймспейсе, что и this аругмент, а не в System.Collections.Generic.Extensions. Я вообще не припомню в AVK>>Это лишнее действие, лишняя строка кода.

IT>Почему лишняя? Очень полезная строка. Позволяет быстро прикинуть, что используется в коде.

Сомнительное достоинство.

AVK>>Тогда зачем вообще соответствие неймспейсов и папок?

IT>Затем, что это предсказуемо.

Но неудобно.

AVK>>Там — нет. А вот в прикладном коде, если бы весь фреймворк был в одном неймспейсе, было бы много просто в силу объема фреймворка.

IT>Давай сразу определимся. Мы тут пишем не прикладной код, а библиотеку общего назначение и требования к ней должны быть соответствующие.

Еще раз. В фреймворке очень много типов, поэтому один неймспейс обладал бы очень высокой вероятностью порождения конфликтов. У нас типов вряд ли будет сильно больше чем в каком нибудь System.Windows.Forms, так что и подобной проблемы тоже нет.

IT>Какая разница сколько там функций?


Большая. Неймспейс становится бесполезным в качестве средства организации и порождает ненужные развесистые деревья каталогов. Мне в свое время хватило жабы с ее жесткой привязкой каталогов к неймспейсам. Независимая структура намного удобнее — МС вполне правильно и осознанно ввели директиву namespace с самого начала.

IT> Да хоть одна. Не вижу никаких проблем. Зато искать будет легко и просто.


Искать и так легко и просто, вызвав Find Symbol.

IT>А если потом к твоим 2-3-м классам добавиться ещё 7-8, то ты их перенесёшь в отдельный неймспейс?


Вероятность такого близка к 0. У нас все таки не большие и сложные вещи предполагаются, которые могут неузнаваемо эволюционировать со временем.

AVK>>А чем тебя в этом качестве не устраивают банальные папки?

IT>Навигация в решарпере — это хорошо. Но тот, кто поставит нугет и будет пользоваться этой библиотекой вряд ли будет качать её исходники и включать её в свой проект ради решарпера.

Тот кто ее поставит — ему вообще будет покласть на структуру папок.

IT> Когда мне нужно посмотреть код в какой-то открытой библиотеке и она находится на гитхабе, то я иду туда и ищу нужный класс ориентируясь прежде всего по неймспейсам.


А я пользуюсь поиском, так быстрее. А если просто глазком взглянуть — просто смотрю декомпилят решарпера.

AVK>>Регулярно вижу обратное.

IT>Мне тоже доводилось такое видеть. Как правило в таких прокетах чёрт ногу сломит. Давай с самого начала и здесь устроим подобный бардак?

Я не считаю это бардаком. Я писал код в том числе и в крупных проектах, и никаких проблем по поводу несоответствия каталогов не испытывал. А вот когда лет 10-15 назад пытались форсить их соответствие, вот тогда это мне сильно мешало.

IT>И что там не так?


Нет точного соответствия папок неймспейсам. Если логическая группировка файлов по фолдерам, но никакой аналогичной группировки по неймспейсам. Так что там с твоими сомнениями в профессиональном уровне разработчиков розлина?

IT>1. Мы делаем не конечный продукт на который никогда не появлится не одного референса, а библиотеку общего назначения.


Еще раз — пользователям библиотеки насрать на организацию файлов по каталогам. Твой пример с ручным поиском по каталогу исходников сильно натянут. Если тебе так уж сильно хочется — можно вообще в автогенеренном хелпе вставить прямую ссылку на исходник. Или поднять source server или воспользоваться готовым, тогда вообще можно будет в студии одним кликом смотреть, да еще и отлаживаться при необходимости.

IT>2. Из каждого правила есть исключения лишь подтверждающие правила.


С этим ты к Владу сходи, он объяснит.

IT> Если есть нормальное логическое обоснование, а не просто личные предпочтения, то всегда можно сделать по-другому. Но не надо это сразу превращать в правило.


Можно теперь попонятнее объяснить, что ты этой фразой хотел сказать? Я вроде понятно объяснил — мне не нравятся лишние ограничения на структуру каталогов, они мне мешают делать эту структуру такой, какой мне хочется. А ты мне какие то асбтракции про исключения и правила втираешь.

IT>>>Для хелперных классов давно уже существует очень простое правило — их следует помещать в неймспейсы с именем неймспейса того класса, для котого делается хелпер.

AVK>>Т.е. помещаем DisposableExtensions в System?

IT>В CodeJam.


Почему именно туда?

IT>Всё касающееся коллекций в CodeJam.Collections.


А почему не в CodeJam.Collections.Generic? Или часть, касающуюся массивов в CodeJam, часть в CodeJam.Enumerable, а часть в CodeJam.Collection?

Я тут еще одну прекрасную вещь про много неймспейсов вспомнил. Ты же помнишь, что называть класс так же, как и часть неймспейса мягко говоря не рекомендуется?

IT>Linq в CodeJam.Linq.


А что такое Linq формально? Вот Concat который у нас — это LINQ? А DisposeAll это LINQ?

IT>И так далее по аналогии.


Я по прежнему не вижу здесь формальной системы.

IT>Т.е. вместо System ставим CodeJam.


Тогда почему не CodeJam.Collections.Generic? И откуда взялся Linq, если в виде неймспейса он только в Xml.Linq?

IT> Ещё я бы не стал всё, касающееся коллекций запихивать в соостветствующие неймспейсы. Collections вполне достаточно.


Вот вот. Все к тому и сводится, что не надо себя ограничивать формализмами там, где в них нет крайней необходимости.

AVK>>Но у IEnumerable неймспейс не Linq, а System.Collections.Generic. У коллекций же их вообще несколько. Как то все очень расплывчато получается.

IT>Это как раз то самое исключение.

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

IT>>> Не думаю, что таких неймспейсов будет много и что это вызовет какие-то сложности при их использовании.

AVK>>Это прежде всего лишние сущности, лишние юзинги и снижение discoverability, хз как это по русски.
IT>Ты же решарпером пользуещься, там это без проблем.

Что там без проблем? Вот сейчас я пишу using CodeJam и при нажатии на точку вижу все расширения. А если раскидать все по неймспейсам, так мне придется вспоминать что в какой неймспейсе находится, либо смотреть список вообще без разграничений по неймспейсам. А вот так чтобы попросить его контекстно показать мне список мемберов в неймспейсе CodeJam.*, такого он пока не умеет, только список типов.

IT>>> более логична и предсказуема.

AVK>>Обоснуй.
IT>Размещая расширения в произвольных папках

Они не произвольные, не надо гипертрофировать. Они просто связаны с неймспейсами нежестко. Я даже согласен на правило, что в одной папке не может быть разных неймспейсов, это вполне нормально и логично. Но вот чтобы я не мог создать подпапки для группировки части файлов, не создавая лишних неймспейсов — тут я не согласен.
Пример розлина я уже приводил. Посмотри теперь в проекте experimental — там есть папка CmdLine.Model.Checking, причем типы там публичные. Ну вот удобно мне так при разработке — поместить этот кусочек модели в отдельную подпапку. А вот нафига при этом еще и в CodeJam.CmdLine.Model.Checking типы засовывать, а потом плодить стадо юзингов и внутри кода библиотеки, и внутри прикладного кода — это мне непонятно.
Лично у меня эвристика папочная простая. Если нужно несколько неймспейсов в одном проекте (потребность в неймспейсе при этом первична и не имеет никакого отношения к папкам) — завожу для каждого отдельную папку. В 95% случаев создавать неймспейсы 3 уровня не требуется. Далее, внутри папок или корня проекта с одним неймспейсом, если вдруг образуется больше двух тесно связанных между собой файлов (не обязательно исходников! ресурсы, картинки и т.п. тоже считаются) — завожу для них отдельную папочку без образования неймспейса. И уж точно боже упаси для группировки пихать несколько типов в один файл.

IT> ты только путаешь тех, кто будет изучать код библиотеки. Открыв проект и увидев папку String первое, что мне придёт в голову, что есть такой namespace CodeJam.String. Или наоборот, если я захочу посмотреть на гитхабе код StringExtensions.Substring, то искать я его буду в корне и очень сильно удивлюсь не найдя его там. И придётся мне с матом бродить по всем папкам. Что касается строк, то проявив смекалку я может быть быстро дойду до папки String, но вот с тем же CharExtensions.IsDigit уже могут быть проблемы.


А как надо? Если использовать то, что ты предлагаешь, то надо и StringExtensions, и CharExtensions кидать в корень, рядом с Disposable, DisposableExtensions, парочкой файлов Fn. Туда же до кучи намешать из коллекций те методы, у которых в параметрах массивчик. Полученная каша правда удобнее? Или это очередное исключение?

IT>Далее. Как я уже говорил, критерий выноса кода в отдельный неймспейс по количеству файлов приведёт либо к бардаку, либо к ломке совместимости в будущем, т.е. ни к чему хорошему.


Ломка совместимости это как раз когда упираться рогом и пытаться на каждый фолдер заводить неймспейс. А бардака никакого не будет, если каталоги не от балды заводить, а с умом.

IT>Наличие открытых неймспейсов в коде — это не лишная, а очень даже полезная информация, которая лично мне сразу даёт представление с чем в данном файле придётся столкнуться.


Ну а лично я туда никогда не заглядываю. Как то информация об использовании чего то в файле не очень интересна — файл почти не фигурирует как значимая сущность при анализе кода.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[16]: Проект утилитной библиотечки
От: IT Россия linq2db.com
Дата: 21.03.16 14:29
Оценка:
Здравствуйте, AndrewVK, Вы писали:

IT>>Почему лишняя? Очень полезная строка. Позволяет быстро прикинуть, что используется в коде.

AVK>Сомнительное достоинство.

Офигительное достоинство, если много работаешь с чужим кодом, а не только со своим.

AVK>>>Тогда зачем вообще соответствие неймспейсов и папок?

IT>>Затем, что это предсказуемо.
AVK>Но неудобно.

Тебе может и не удобно. Или ты этот проект затеял исключительно для себя?

AVK>Еще раз. В фреймворке очень много типов, поэтому один неймспейс обладал бы очень высокой вероятностью порождения конфликтов. У нас типов вряд ли будет сильно больше чем в каком нибудь System.Windows.Forms, так что и подобной проблемы тоже нет.


Т.е. у нас будет всего немного. Ага. Ставим сюда закладку.

IT>>Какая разница сколько там функций?


AVK>Большая. Неймспейс становится бесполезным в качестве средства организации и порождает ненужные развесистые деревья каталогов. Мне в свое время хватило жабы с ее жесткой привязкой каталогов к неймспейсам. Независимая структура намного удобнее — МС вполне правильно и осознанно ввели директиву namespace с самого начала.


Тем не менее MS не часто отходит от правила "один неймспейс — один фолдер".

IT>> Да хоть одна. Не вижу никаких проблем. Зато искать будет легко и просто.

AVK>Искать и так легко и просто, вызвав Find Symbol.

Ещё раз. Это если у тебя есть Find Symbol, а если у тебя есть только браузер, то не легко и не просто.

IT>>А если потом к твоим 2-3-м классам добавиться ещё 7-8, то ты их перенесёшь в отдельный неймспейс?

AVK>Вероятность такого близка к 0. У нас все таки не большие и сложные вещи предполагаются, которые могут неузнаваемо эволюционировать со временем.

Ой я тебя умоляю. Если есть вероятность чего-то плохого, то это обязательно произойдёт. Ты как будто не программист.

AVK>Я не считаю это бардаком. Я писал код в том числе и в крупных проектах, и никаких проблем по поводу несоответствия каталогов не испытывал. А вот когда лет 10-15 назад пытались форсить их соответствие, вот тогда это мне сильно мешало.


А я считаю это самым натуральным бардаком. В библиотеке 3 класса, а найти что-нибудь в ней может только тот, кто их писал. Афигенный порядок.

IT>>И что там не так?

AVK>Нет точного соответствия папок неймспейсам.

Да там всего три файла в одном неймспейсе, какие папки?

IT>>1. Мы делаем не конечный продукт на который никогда не появлится не одного референса, а библиотеку общего назначения.

AVK>Еще раз — пользователям библиотеки насрать на организацию файлов по каталогам.

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

IT>>2. Из каждого правила есть исключения лишь подтверждающие правила.

AVK>С этим ты к Владу сходи, он объяснит.

О, да. Как раз у нас Влад большой любитель прогибать логику под свои предпочтения.

IT>> Если есть нормальное логическое обоснование, а не просто личные предпочтения, то всегда можно сделать по-другому. Но не надо это сразу превращать в правило.

AVK>Можно теперь попонятнее объяснить, что ты этой фразой хотел сказать? Я вроде понятно объяснил — мне не нравятся лишние ограничения на структуру каталогов, они мне мешают делать эту структуру такой, какой мне хочется. А ты мне какие то асбтракции про исключения и правила втираешь.

Объясняю. Ограничения существуют, чтобы им следовали, не обязательно жёстко, но следовали. А для тебя похоже они существуют исключительно, чтобы их сразу нарушать.

IT>>>>Для хелперных классов давно уже существует очень простое правило — их следует помещать в неймспейсы с именем неймспейса того класса, для котого делается хелпер.

AVK>>>Т.е. помещаем DisposableExtensions в System?

IT>>В CodeJam.

AVK>Почему именно туда?

А что здесь непонятног?

IT>>Всё касающееся коллекций в CodeJam.Collections.

AVK>А почему не в CodeJam.Collections.Generic?

Можно и туда, но думаю, CodeJam.Collections достаточно.

AVK>Я тут еще одну прекрасную вещь про много неймспейсов вспомнил. Ты же помнишь, что называть класс так же, как и часть неймспейса мягко говоря не рекомендуется?


Не помню.

IT>>Linq в CodeJam.Linq.

AVK>А что такое Linq формально? Вот Concat который у нас — это LINQ? А DisposeAll это LINQ?

Чего эти классы хелперы?

AVK>Тогда почему не CodeJam.Collections.Generic? И откуда взялся Linq, если в виде неймспейса он только в Xml.Linq?


Откуда?

IT>> Ещё я бы не стал всё, касающееся коллекций запихивать в соостветствующие неймспейсы. Collections вполне достаточно.

AVK>Вот вот. Все к тому и сводится, что не надо себя ограничивать формализмами там, где в них нет крайней необходимости.

Судя по твоим рассуждениям у тебя вообще нет ниобходимости ни в каких правилах. Это как раз то, что я называл нелогичностью и непредсказуемостью. И это делается с самого начала, а что будет дальше?

AVK>Ну то есть теория не работает, давай заткнем дырку красивой пословицей? Или все таки признаем, что не надо себя в ненужные рамки загонять?


Ну не надо рамок, так нк надо. Один местный проект без рамок у нас уже есть.

AVK>Пример розлина я уже приводил.


В том примере три класса по 20 строчек и один неймспейс.

AVK>Посмотри теперь в проекте experimental — там есть папка CmdLine.Model.Checking, причем типы там публичные. Ну вот удобно мне так при разработке — поместить этот кусочек модели в отдельную подпапку. А вот нафига при этом еще и в CodeJam.CmdLine.Model.Checking типы засовывать, а потом плодить стадо юзингов и внутри кода библиотеки, и внутри прикладного кода — это мне непонятно.


Посмотрел. Похоже в CmdLine неслабый монстрик зарождается. Там делов максимум на 200 строк кода, а у нас уже 3 папки и 25 классов. Даже не знаю что тут и посоветовать.

Кстати, от подобной практики, когда модель убирается в отдельную папку я уже давно отказался даже в WPF. На практике крайне не удобно бегать из папки в папку, работая по сути над одной и той же вещью.

AVK>А как надо? Если использовать то, что ты предлагаешь, то надо и StringExtensions, и CharExtensions кидать в корень, рядом с Disposable, DisposableExtensions, парочкой файлов Fn. Туда же до кучи намешать из коллекций те методы, у которых в параметрах массивчик. Полученная каша правда удобнее? Или это очередное исключение?


Я вообще не вижу смысла разбивать расширения со строками и символами на пять файлов. Всё можно поместить в один, а группы методов разделаить регионами и, опаньки, проблема с папкой исчезает сама собой.

AVK>Ломка совместимости это как раз когда упираться рогом и пытаться на каждый фолдер заводить неймспейс. А бардака никакого не будет, если каталоги не от балды заводить, а с умом.


Да бардак уже есть. При этом базируется он на твоих рассуждениях. в которых я никак не уловлю логики. С одной стороны ты говоришь, что у нас в проекте классов будет немного, поэтому неймспейсы не нужны. С другой, у нас много файлов, поэтому нужны папки.

Короче. Обсуждать это я больше не намерен, т.к. похоже, что стороны пришли к взаимному несогласию и дальшее обсуждени лишено всякого смысла. Делай как считаешь нужным.
Если нам не помогут, то мы тоже никого не пощадим.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.