В общем вот GitHub PathInfo.cs простой модуль. Оформлено примерно до 80-90% готовности, но основные вещи используются уже давно.
Это враппер для System.IO.Path, File, Directory, их полный 100% порт в объект PathInfo и дополнительные плюшки.
Ближайшие аналоги которые я нашел FluentPath и NDepend.Helpers, если кто еще найдет прошу мне подсказать.
Обязательно к применению абсолютно во всех проектах, с этим модулем у вас поднимется урожайность, производительность, продуктивность и плодовитость, повысятся надои, увеличатся бегучесть, плывучесть и прыгучесть. Ждем включения в следующую версию фреймворка.
Код будет компактнее и понятнее.
Прошу посмотреть и сказать мне, нужно ли это допиливать до совершенства или забросить куда подальше.
Здравствуйте, grosborn, Вы писали:
G>В общем вот GitHub PathInfo.cs простой модуль.
фигасе простой G>Прошу посмотреть и сказать мне, нужно ли это допиливать до совершенства или забросить куда подальше.
Я бы забросил. Но если вдруг решитесь допиливать — как минимум CompareTo и Equals реализованы из рук вон плохо, будут ломать сортировку на раз.
G>>В общем вот GitHub PathInfo.cs простой модуль. S>фигасе простой G>>Прошу посмотреть и сказать мне, нужно ли это допиливать до совершенства или забросить куда подальше. S>Я бы забросил. Но если вдруг решитесь допиливать — как минимум CompareTo и Equals реализованы из рук вон плохо, будут ломать сортировку на раз.
Если я это два дня пилил, то завтра могу остальное запилить если не лень будет.
CompareTo и Equals
вроде бы проверял на эффективность, а что там не так? Сортировка она же ведь не по полному пути, а на каждом уровне. Конкретно этот код сравнения я вчера написал и действительно он еще не обкатан и не доведен до блеска. Можешь свои замечания сказать?
Он простой в том смысле, что если ты знаешь Path,File и Directory, то ты знаешь все и про этот модуль, ибо он 100% порт. То есть ты помнишь что есть такой статик метод File.Copy(,) -> у PathInfo всем им есть полный аналог их вызывающий, это FileCopy(). то есть ничего нового изучать не требуется.
Здравствуйте, grosborn, Вы писали:
G>вроде бы проверял на эффективность, а что там не так? Сортировка она же ведь не по полному пути, а на каждом уровне. Конкретно этот код сравнения я вчера написал и действительно он еще не обкатан и не доведен до блеска. Можешь свои замечания сказать?
Дело не в эффективности, а в ошибке реализации логики.
Замечания не мои, они MSDN-овские.
Вот, например http://msdn.microsoft.com/en-us/library/system.icomparable.compareto.aspx, см. Notes to Implementers.
Еще ближе:
If A.CompareTo(B) returns a value other than zero, then B.CompareTo(A) must return a value of the opposite sign.
Это условие не выполнится в случае сравнения двух путей, у которых Empty true. Это то что в глаза бросилось, полное соответствие требованиям я не проверял.
Здравствуйте, grosborn, Вы писали:
G>Он простой в том смысле, что если ты знаешь Path,File и Directory, то ты знаешь все и про этот модуль, ибо он 100% порт. То есть ты помнишь что есть такой статик метод File.Copy(,) -> у PathInfo всем им есть полный аналог их вызывающий, это FileCopy(). то есть ничего нового изучать не требуется.
А зачем тогда нужен FileCopy? Он это делает лучше чем File.Copy?
S>Это условие не выполнится в случае сравнения двух путей, у которых Empty true. Это то что в глаза бросилось, полное соответствие требованиям я не проверял.
G>>Он простой в том смысле, что если ты знаешь Path,File и Directory, то ты знаешь все и про этот модуль, ибо он 100% порт. То есть ты помнишь что есть такой статик метод File.Copy(,) -> у PathInfo всем им есть полный аналог их вызывающий, это FileCopy(). то есть ничего нового изучать не требуется. S>А зачем тогда нужен FileCopy? Он это делает лучше чем File.Copy?
Легче читается нотация файловых операций.
File.Copy(Path.Combine(path1, path2), path);
// против
path1.Combine(path2).FileCopy(path);
// или еще лучше
(path1 / path2).FileCopy(path);
лучше воспринимается, быстрее набор кода через автодополнение. Linq работает, функциональный стиль. В общем получается читабельный код, а не макаронник.
Здравствуйте, grosborn, Вы писали:
S>>А зачем тогда нужен FileCopy? Он это делает лучше чем File.Copy?
G>Легче читается нотация файловых операций.
Не уверен на 100%
G>File.Copy(Path.Combine(path1, path2), path);
Отлично
G>// против
G>path1.Combine(path2).FileCopy(path); G>// или еще лучше G>(path1 / path2).FileCopy(path);
G>лучше воспринимается, быстрее набор кода через автодополнение. Linq работает, функциональный стиль. В общем получается читабельный код, а не макаронник.
Мне сложно воспринимать семантику Путь.КопируйФайл(путь). Сложнее разве что только Строка.КопируйФайл(строка).
Линк работает и без этого кода, а для функционального стиля слишком много императива.
G>>лучше воспринимается, быстрее набор кода через автодополнение. Linq работает, функциональный стиль. В общем получается читабельный код, а не макаронник. S>Мне сложно воспринимать семантику Путь.КопируйФайл(путь). Сложнее разве что только Строка.КопируйФайл(строка). S>Линк работает и без этого кода, а для функционального стиля слишком много императива.
Но против уменьшения количества буковок ты же не сможешь возразить? Экономия до 10-50 символов в строке в новой нотации. Ну же, соглашайся?
Здравствуйте, grosborn, Вы писали:
G>>>лучше воспринимается, быстрее набор кода через автодополнение. Linq работает, функциональный стиль. В общем получается читабельный код, а не макаронник. S>>Мне сложно воспринимать семантику Путь.КопируйФайл(путь). Сложнее разве что только Строка.КопируйФайл(строка). S>>Линк работает и без этого кода, а для функционального стиля слишком много императива.
G>Но против уменьшения количества буковок ты же не сможешь возразить? Экономия до 10-50 символов в строке в новой нотации. Ну же, соглашайся?
можно пример с экономией в 50 буковок? Только не надо писать Path.Combine(Path.Combine(Path.Combine(...)))
Экономия на буковках ценой семантики — идея не очень. Да и если прижмет сэкономить, мне не долго написать пару методов хелперов.
G>>>>лучше воспринимается, быстрее набор кода через автодополнение. Linq работает, функциональный стиль. В общем получается читабельный код, а не макаронник. S>>>Мне сложно воспринимать семантику Путь.КопируйФайл(путь). Сложнее разве что только Строка.КопируйФайл(строка). S>>>Линк работает и без этого кода, а для функционального стиля слишком много императива.
А где-нибудь в твоих проектах есть примеры работы с путями или именами фалов? Может ты запостишь кусочек, я перепишу и посмотрим.
G>>Но против уменьшения количества буковок ты же не сможешь возразить? Экономия до 10-50 символов в строке в новой нотации. Ну же, соглашайся? S>можно пример с экономией в 50 буковок? Только не надо писать Path.Combine(Path.Combine(Path.Combine(...)))
Нет, я взял пример из предыдущей своей ветки
public static readonly string USER_DATA_DIR = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kotonoha");
иногда эти портянки довольно велики, а с переносами и вообще нечитаемы.
S>Экономия на буковках ценой семантики — идея не очень.
Лично я считаю читабельность кода важнее. Но просто ты по своим предпочтением завалил все остальные мои аргументы и читабельность тебя почему-то не впечатлила. Остались только буковки.
S>Да и если прижмет сэкономить, мне не долго написать пару методов хелперов.
Идеи с хелперами мне всегда не нравились потому что если это хелпер к строке пути, то мы загрязняем методами расширения строку, что потом лезет везде в автодополнение во всех местах. Поэтому расширения строки не использую.
Здравствуйте, grosborn, Вы писали:
S>>>>Линк работает и без этого кода, а для функционального стиля слишком много императива.
G>А где-нибудь в твоих проектах есть примеры работы с путями или именами фалов? Может ты запостишь кусочек, я перепишу и посмотрим.
Ничего экстраординарного.
S>>можно пример с экономией в 50 буковок? Только не надо писать Path.Combine(Path.Combine(Path.Combine(...)))
G>Нет, я взял пример из предыдущей своей ветки
G>
о, показательный пример. Обсудим.
Итак, первая часть — несокращаемая. Это "public static readonly string". Ну там можно сократить разве что до "public static readonly Path", но это не спортивно, т.к. строку тоже можно using-ом во что-то перекроить.
Дальше Path.Combine. Не самая длинная часть, предлагаю ее пока оставить как есть.
Вот по поводу Environment.GetFolderPath(...) и Environment.SpecialFolder.LocalApplicationData — тут я поддерживаю, это немного избыточно. Я бы оставил Environment.SpecialFolders.LocalApplicationData. Причем, не уверен что это вообще касается Environment BCL, т.к. фреймворк-то задумывался как межплатформенный. В идеале было бы что-то вроде Microsoft.Windows.SpecialFolders.LocalApplicationData, причем Microsoft.Windows — это namespace, SpecialFolders — класс, а LocalApplicationData — статическое свойство. Enum тоже нужен, и GetFolderPath с ним нужен, но для специальных случаев. А когда мы точно знаем что путь будет LocalApplicationData, GetFolderPath избыточен.
Итак, в идеале мой код был бы такой:
using Microsoft.Windows;
public static readonly string USER_DATA_DIR =
Path.Combine(SpecialFolders.LocalApplicationData, "Kotonoha");
И для него достаточно лишь "выпрямить" SpecialFolders.
Понятно, что можно сэкономить за счет SpecialFolders.LocalApplicatoinData.Combine("Kotonoha"), но я не поклонник таких экономий. К слову сказать, enumerable1.Combine(enumerable2) мне тоже не нравится и я часто пишу Enumerable.Combine(enumerable1, enumerable2).
G>иногда эти портянки довольно велики, а с переносами и вообще нечитаемы.
Есть хороший прием, называется Introduce Local. Со статическими перменными тоже работает.
S>>Экономия на буковках ценой семантики — идея не очень.
G>Лично я считаю читабельность кода важнее. Но просто ты по своим предпочтением завалил все остальные мои аргументы и читабельность тебя почему-то не впечатлила. Остались только буковки.
Читабельность не выражается в 1/(число буковок).
S>>Да и если прижмет сэкономить, мне не долго написать пару методов хелперов.
G>Идеи с хелперами мне всегда не нравились потому что если это хелпер к строке пути, то мы загрязняем методами расширения строку, что потом лезет везде в автодополнение во всех местах. Поэтому расширения строки не использую.
Поддерживаю. Хотя, по началу любил юзать "[{0}]".Format(someValue) вместо String.Format(....
Но потом и это отпало.
S>И для него достаточно лишь "выпрямить" SpecialFolders. S>Понятно, что можно сэкономить за счет SpecialFolders.LocalApplicatoinData.Combine("Kotonoha"), но я не поклонник таких экономий. К слову сказать, enumerable1.Combine(enumerable2) мне тоже не нравится и я часто пишу Enumerable.Combine(enumerable1, enumerable2).
G>>иногда эти портянки довольно велики, а с переносами и вообще нечитаемы. S>Есть хороший прием, называется Introduce Local. Со статическими перменными тоже работает.
Не совсем понял о чем ты.
S>Поддерживаю. Хотя, по началу любил юзать "[{0}]".Format(someValue) вместо String.Format(.... S>Но потом и это отпало.
Та же беда. Но если бы "[{0}]".Format(someValue) был искаробки, то я бы предпочел им пользоваться, а не String.Format(
S>И для него достаточно лишь "выпрямить" SpecialFolders. S>Понятно, что можно сэкономить за счет SpecialFolders.LocalApplicatoinData.Combine("Kotonoha"), но я не поклонник таких экономий. К слову сказать, enumerable1.Combine(enumerable2) мне тоже не нравится и я часто пишу Enumerable.Combine(enumerable1, enumerable2).
Тут ты неправ. Для читабельности кода строка начинающаяся с Enumerable.Combine( и Path.Combina( сильно вредит. Строка должна начинаться со смысловой нагрузки сужающей контекст, а не с глобального метода понять который мы можем только прочитав его аргументы.
Начало выражения Enumerable.Combine( не сужает контекст выбора и для понимания и для подсказки автовыбора, а начало выражения с первого аргумента сужает. Так что тут ты объективно не прав.
Здравствуйте, grosborn, Вы писали:
S>>Понятно, что можно сэкономить за счет SpecialFolders.LocalApplicatoinData.Combine("Kotonoha"), но я не поклонник таких экономий. К слову сказать, enumerable1.Combine(enumerable2) мне тоже не нравится и я часто пишу Enumerable.Combine(enumerable1, enumerable2).
G>Это то чего нет, но хотелось бы. А вот что есть:
G>Самый близкий к твоему варианту предпоследний.
Они почти все (кроме 2) близки с точностью до вызова Combine (места либо отсутствия вызова).
G>>>иногда эти портянки довольно велики, а с переносами и вообще нечитаемы. S>>Есть хороший прием, называется Introduce Local. Со статическими перменными тоже работает.
G>Не совсем понял о чем ты. http://www.jetbrains.com/resharper/webhelp/Refactorings__Introduce_Variable.html
S>>Поддерживаю. Хотя, по началу любил юзать "[{0}]".Format(someValue) вместо String.Format(.... S>>Но потом и это отпало.
G>Та же беда. Но если бы "[{0}]".Format(someValue) был искаробки, то я бы предпочел им пользоваться, а не String.Format(
угу
Здравствуйте, grosborn, Вы писали:
S>>И для него достаточно лишь "выпрямить" SpecialFolders. S>>Понятно, что можно сэкономить за счет SpecialFolders.LocalApplicatoinData.Combine("Kotonoha"), но я не поклонник таких экономий. К слову сказать, enumerable1.Combine(enumerable2) мне тоже не нравится и я часто пишу Enumerable.Combine(enumerable1, enumerable2).
G>Тут ты неправ. Для читабельности кода строка начинающаяся с Enumerable.Combine( и Path.Combina( сильно вредит. Строка должна начинаться со смысловой нагрузки сужающей контекст, а не с глобального метода понять который мы можем только прочитав его аргументы. G>Начало выражения Enumerable.Combine( не сужает контекст выбора и для понимания и для подсказки автовыбора, а начало выражения с первого аргумента сужает. Так что тут ты объективно не прав.
не понял в чем я не прав. Path.Combine прекрасно сужает контекст. Что бы понять, что он делает, вовсе не обязательно читать аргументы.
Автовыбор меня мало беспокоит, т.к. я код больше читаю чем пишу.
Повторюсь. Путь.Комбинируйся с другим путем для меня — порно. Так же как и Путь.КопируйФайл(другойПуть). Так же как и объект.Сравнись(другойОбъект).
Вот путь / другойПуть — это хорошо. Но ради этого не стоит писать столько кода. Префиксная запись не сильно хуже в данном случае.
Здравствуйте, grosborn, Вы писали:
G>Тут ты неправ. Для читабельности кода строка начинающаяся с Enumerable.Combine( и Path.Combina( сильно вредит. Строка должна начинаться со смысловой нагрузки сужающей контекст, а не с глобального метода понять который мы можем только прочитав его аргументы. G>Начало выражения Enumerable.Combine( не сужает контекст выбора и для понимания и для подсказки автовыбора, а начало выражения с первого аргумента сужает. Так что тут ты объективно не прав.
Чуть отвлекись от программинга, взгляни на проблему шире, с другой точки зрения.
Когда мы видим математическое выражение 2 + 3, то часто так и произносим: "два плюс три". Но часто говорим по-другому: "сложить два и три". Ведь так? Объективно? Теперь переведём второе выражение в код: сложить(2, 3), то есть Path.Combine...