Здравствуйте, adontz, Вы писали:
A>С другой стороны, сделать нормальный интерфейс, усложнив внутренее устройство, и, как следствие, потратить на разработку, включая отладку, больше времени, может быть, в целом, выгоднее по времени и деньгам.
"Пилите Шура, пилите..." =)))
Здравствуйте, IB, Вы писали:
IB>Вся проблема в том, что он вносится один раз, а обнаруживается в очень многих местах. IB>Тезис же о том, что правится такой баг только один раз, так же сомнителен, на практике ошибка в библиотеке зачастую выливается в серию воркэраундов в приложениях, которые ее используют, так как править библиотеку дорого и не всегда возможно.
Не надо всё лепить в одну кучу, проблемы архитуктуры и плохой саппорт (закрытость исходников).
IB>Потом выходит новая версия библиотеки, с уже исправленым багом, и бедный разработчик ставится в раскоряку, так как уже потрачены драгоценные человеко-дни на обход бага, теперь, вроде бы, надо писать новый код без лишних приседаний, но и старый выкидывать нельзя, так как есть активные ветки кода, которые используют старую версию. И вот, наш герой стоит перед суровой неизбежностью поддерживать две версии работы с библиотекой — с багом и без бага... (Дальше идет плачь о выкинутых деньгах, потраченном времени, провалу по срокам проекта, а дома детки не кормлены). Но! Зато API у библиотеки, чудо как удобен..
Весьма душещипательная история, но те платные библиотеки с которыми я работал чинились максимум за неделю. Конечно, при выборе библиотеки важен так же и саппорт, но это совсем не имеет отношения к обсуждаемому вопросу.
A>> И кто отстаивает, мягко говоря, сомнительные идеи? IB>Ты конечно. Например, идея бросить все на алтарь удобства просто восхитительный образец сомнительности.
Не всё, я не фанатик. Ровно столько, сколько надо.
A>> не просит все методы какие можно засовывать в классы, не просит все методы какие можно доставать из классов, IB>Ну да, просто размажем все ровным слоем, как левая пятка захочет, зато эстетика соблюдена..
Ну если пользователя библиотеки зовут Левая Пятка, то да, именно так как захочет мистер Левая Пятка.
IB>проблемы с пониманием идеи конфигурации...
Не проблемы. Просто непривычно, а следовательно неудобно. Ты же понимаешь как летит самолёт, но понимать как он летит и управлять им всё же разные вещи.
Здравствуйте, AndrewVK, Вы писали:
AVK>А главная проблема — что писалось "как удобнее", а не как по нормальному. К примеру — вместо нормальной модели драйверов нужно наследоваться от специального класса, в котором гора виртуальных методов.
Андрей, ты так и не понял? Как удобнее, нон е создателю, а пользователю. Как как удобнее автору реструктуризатора, а как удобнее тебе. Если тебе не удобно пользоваться (наследование от непонятного класса, ещё что-то), то интерфейс плохой, библиотека плохая. ТОЧКА.
AVK>
С другой стороны, сделать нормальный интерфейс, усложнив внутренее устройство, и, как следствие, потратить на разработку, включая отладку, больше времени, может быть, в целом, выгоднее по времени и деньгам.
OK, сузим. Если пользователю будет заметно удобнее пользоваться библиотекой когда метод внутри класса, если, когда метод внутри класса, объект программный будет в большей степени соответствовать объекту из предметной области и это сделает интерфейс библиотеки интуитивно понятным в большей степени, то чхать я хотел на увеличение инкапуляции. Я пишу библиотеку для пользователй и мне должно быть сложно за счёт того что им легко, по определению.
Здравствуйте, IB, Вы писали:
IB>WCF, любой IoC контейнер.
Не оставалось никаких сомнений, что фургоны Вудли Пойндекстера шли по следам своих же колес.
— Наши следы! — пробормотал Колхаун; сделав это открытие, он натянул поводья и разразился проклятиями.
— Наши следы? Что ты этим хочешь сказать, Кассий? Неужели мы едем...
— ...по нашим собственным следам. Да, именно это я и хочу сказать. Мы описали полный круг. Смотрите: вот заднее копыто моей лошади — отпечаток половины подковы, а вот следы негров.
(с)
Ладно, контрпример: Spring.Net ISet, методы AddAll, RemoveAll. Единственные их имплементации используют только публичный контракт. Причем контракт интерфейса, как раз тот случай где еще удобство тестирования сыграет. Заодно и контракт ограничим.
По всем аргументам прозвучавшим в ветке отличные кандидаты для выноса в SetCollectionOperationService или еще куда, я не спец по таким выносам.
Косяк дизайна?
Z>>Как должны выглядеть эти классы/класс? IB>Как внешний класс или сервис.
Так сложно написать несколько строк контрактов? Может быть я спорю просто не разглядев очевидную логичность данного решения.
Z>>Да ничего подобного, читабельность кода не поддается автоматической оценке, не существует метрик ее измеряющих. Тем не менее она может стать самой серьезной проблемой при модификации/расширении. IB>Только вопрос — ухудшает ли читаемость предлагаемый подход остается открытым.
Вот контракты которые второй пост прошу увижу и посмотрим.
Z>>То, что некоторые метрики можно выразить числом еще не означает, что они доминирующие. IB>Это не означает, что их можно игнорировать.
Я где-то призывал их игнорировать? Я всеголишь считаю, что ориенитруясь только на задирание данных материк вверх многого не добьешься.
Здравствуйте, adontz, Вы писали:
A>Я так понимаю, единственная (ну или самая существенная с большим отрывом от других) проблема Реструктуризатора в том, что он написан без использования внешних манипуляров-хелперов,
Проблема в том, что он написан так, что куча методов реализованы там, где их "удобно использовать".
A> как следствие код менее инкапсулирован чем хотелось бы и это в итоге привело к большому количеству проблем.
Именно. Это привело к полной невозможности как модифицировать его код, так и использовать. Любая правка приводит к вылету в самом неожиданном месте, очень познавательный эффект..
A> Потому что мы тут обсуждаем хелперы
Хелперы обсуждаешь ты. Дискуссия же, напоминаю, ведется о том, где держать код метода пользующийся публичным контрактом класса — в классе или вне его.
Здравствуйте, adontz, Вы писали:
A>Андрей, ты так и не понял? Как удобнее, нон е создателю, а пользователю.
Это ты не понял — я говорил про пользователей, про тех, кто драйвера к замечательному реструктуризатору должен писать. Ведь отнаследоваться от одного класса и перекрыть несколько методов проще, чем разбираться с моделью драйверов и специализированными сервисами их обеспечения.
A>OK, сузим. Если пользователю будет заметно удобнее пользоваться библиотекой когда метод внутри класса, если, когда метод внутри класса, объект программный будет в большей степени соответствовать объекту из предметной области и это сделает интерфейс библиотеки интуитивно понятным в большей степени, то чхать я хотел на увеличение инкапуляции. Я пишу библиотеку для пользователй и мне должно быть сложно за счёт того что им легко, по определению.
Ну так чем меньше и специализированнее публичные контракты базовых сущостей библиотеки, тем проще поддерживать изменения кода, который ее использует.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, IB, Вы писали:
A>> Потому что мы тут обсуждаем хелперы IB>Хелперы обсуждаешь ты. Дискуссия же, напоминаю, ведется о том, где держать код метода пользующийся публичным контрактом класса — в классе или вне его.
Если это внешний интерфейс библиотеки, в классе. Если внутренности библиотеки или приложение, можно и в хелперах, если от этого есть польза. Плюс надо учитывать недостатки (убогость) статических методов, включая extension methods.
Здравствуйте, Ziaw, Вы писали:
Z>Косяк дизайна?
Весьма вероятно, я не краевед по Spring.Net
Z>Так сложно написать несколько строк контрактов?
Что это тебе даст? Ты можешь написать их сам, если очень хочется.
Z> Может быть я спорю просто не разглядев очевидную логичность данного решения.
Возможно.
Z>Я всеголишь считаю, что ориенитруясь только на задирание данных материк вверх многого не добьешься.
Я где-то писал, что ориентируюсь только на задирание данных метрик?
Здравствуйте, AndrewVK, Вы писали:
AVK>Это ты не понял — я говорил про пользователей, про тех, кто драйвера к замечательному реструктуризатору должен писать. Ведь отнаследоваться от одного класса и перекрыть несколько методов проще, чем разбираться с моделью драйверов и специализированными сервисами их обеспечения.
Ты меня запутал. В чём проблема с драйверами?
AVK>Ну так чем меньше и специализированнее публичные контракты базовых сущостей библиотеки, тем проще поддерживать изменения кода, который ее использует.
Да, только базовые сущности библиотеки должны как-то соответсвовать предметной области работы библиотеки. Если тебе удобнее разделить Солнце на СолнцеСвет и СолнцеТепло и это торчит наружу, то, надо заметить, нигде кроме библиотеки Солнце разделено не будет и у пользователя, после каждого взгляда на небо, будет чуть более съехавшая крыша и чуть более богатый словарный запас ненормативной лексики.
Здравствуйте, IB, Вы писали:
IB>"Пилите Шура, пилите..." =)))
Если вы огласитесь на мой проект, то спускаться из города на пристань вы будете по мраморным лестницам! Васюки станут центром десяти губерний! Что вы раньше слышали о городе Земмеринге? Ничего! А теперь этот городишко богат и знаменит только потому, что там был организован международный турнир, Поэтому я говорю: в Васюках надо устроить международный шахматный турнир.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, IB, Вы писали:
IB>>В том-то и дело, что для C++, для C# вы так и не смогли привести ни одного убедительного сценария.
A>Тебе уже сто раз сказали, удобство важнее твоих фантиков.
A>Давай поставим вопрос ребром, зачем ты вообще решил увеличивать инкапуляцию? Ради упрощения поддержки?
Для упрощения дальнейших модификаций, поскольку продукту нужна не только поддержка, но и дальнейшее развитие. Не эволюционирующий софт — мертвый софт(с). И критерием тут служит не сколько удобство модификаций, сколько их количество. Т.е. результативнее снизить количество необходимых изменений, а не улучшать их "удобство". Как минимум, уменьшается объем потенциально возможных ошибок, набор тестов, да и просто количество необходимого времени.
Принципы подобные SRP, которые применяют для управления зависимостями, как раз и предназначены для минимизации области изменения взаимодействующих объектов. Ответственность, в терминах SRP, это просто причина возможных изменений, и один класс должен иметь только одну причину для изменения.
A>Ладно, я согласен, поддержка упростилась. Зачем тебе упрощать поддержку? Да всё очень просто, чтобы разработка стала дешевле.
Дело не только в разработке как таковой: Проект живет, заказчики требуют новых возможнотей. Соответственно требуются изменения в коде. А вот снижение количества изменений, снижение количества потенциально возможных багов порожденных этими изменениями, снижение объемов тестирования, уменьшение времени, затраченного на эти изменения, увеличиние скорости реализации новых фич и т.п., — все это тоже в конечном итоге средства снижения стоимости и увеличения конкурентноспособности. "Обратная" сторона медали — адекватная архитектура, способствующая к этому... А SRP — это просто один из принципов ее достижения.
A>Теперь о главном. Жадный алгоритм не работает. Совсем. Оптимизировав цену каждого модуля в отдельности ты не получишь в итоге самый дешёвый проект. Причина тому проста — разные модули повторно используются разное количество раз и в разном объёме: некоторые вообще не используются повторно, а некоторые десятки раз.
Повторному использованию, имхо, очень часто мешают лишние ответственности.
>Стоимость функционала в библиотеке — это конечная стоимость, конечная стоимость функционала вне библиотеки — сумма стоимостей во всех приложениях. Это очевидная истина. Потому и пишут библиотеки, чтобы удешевлять, чтобы создать дорогой код, цена которого рассется по всем использующим его проектам.
А такой код(библиотечный) тем более должен стремится к применению SRP по максимуму. Если я хочу от библиотеки 'A', то она и должна мне предоставить 'A', а не ['A' + 'B' + на всякий случай 'C' для удобства] в одном флаконе. Это просто снижает повторное использование(вместе с окупаемостью).
A>Конечно можно удешевить библиотеку оставив MiddleString внутри класса String, и вынеся LeftSubstring и RightSubstring наружу, как нам наивно предлагает AndrewVK.
Можно пойти еще дальше и оставить только два итератора, плюс сделать строку иммутабельной и добавить string builder.
A>Можно удешевить библиотеку и... удорожить проект, потому что каждая минута, когда программист попадает в ступор не находя нужного метода, каждая минута, когда программист вспоминает что метод был, но не помнит где, каждая минута, когда он роется в документации, каждая менитура рефакторинга с метода который вспомнили, на метод который оптимален, оплачивается....
Т.е. автокомплит, если я правильно понял всю ветку — это и есть удобство ?
Здравствуйте, AndrewVK, Вы писали:
AVK>Если их использовать по делу
Золотые слова.
AVK>никаких таких фатальных недостатков у них нет.
Я знаю, как минимум, два.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Console35
{
class Test
{
}
static class TestExtender
{
public static/* virtual ага, щас, разбежался */void ExtensionMethod(this Test test)
{
}
}
class Program
{
static void Main(string[] args)
{
Test t = null;
t.ExtensionMethod(); // Опа, для кого мы это вызвали?!
}
}
}
Здравствуйте, adontz, Вы писали:
AVK>>Это ты не понял — я говорил про пользователей, про тех, кто драйвера к замечательному реструктуризатору должен писать. Ведь отнаследоваться от одного класса и перекрыть несколько методов проще, чем разбираться с моделью драйверов и специализированными сервисами их обеспечения.
A>Ты меня запутал. В чём проблема с драйверами?
Ну как же. Текущий вариант для создания драйвера — это огромный класс, от которого наследуешься и перекрываешь нужные тебе мметоды. Причем перекрыть можно почти любой аспект работы реструктуризатора, потому что этот базовый класс по сути реструктуризатор в себе и содержит. И кроме этого класса не надо больше никаких других.
Тем не менее, если хоть немного включить голову, то понятно, что алгоритмы сравнения схем нужно вынести в отдельный класс, занимающийся сравнением, код, который непосредственно модифицирует базу — в отдельный класс, куча методов сравнения элементов схемы из классов схемы в хелпер, код загрузки схем из БД и ресурсов — тоже должны быть отдельными классами и т.п.
A>Да, только базовые сущности библиотеки должны как-то соответсвовать предметной области работы библиотеки.
И при чем тут распределение методов по классам?
A> Если тебе удобнее разделить Солнце на СолнцеСвет и СолнцеТепло и это торчит наружу, то, надо заметить, нигде кроме библиотеки Солнце разделено не будет и у пользователя
Это всегда будет так — пользователь всегда будет добавлять свои, специфичные алгоритмы, и добавлять он их скорее всего будет не при помощи наследования от классов библиотеки.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, adontz, Вы писали:
A>Не надо всё лепить в одну кучу, проблемы архитуктуры и плохой саппорт (закрытость исходников).
Рома, не увиливай, ни плохой саппорт, ни за крытость исходников тут не причем..
A>Весьма душещипательная история,
Надеюсь не менее душещипательная чем твоя.
A>Не всё, я не фанатик.
Меня терзают смутные сомненья. "Ну если пользователя библиотеки зовут Левая Пятка, то да, именно так как захочет мистер Левая Пятка." (с)
A>Ровно столько, сколько надо.
О, как ты быстро назад сдаешь.. ) А сколько надо? На глазок решишь?
A>Не проблемы. Просто непривычно, а следовательно неудобно.
App.config — не очень неудобен? Не жмет?
Что может быть непривычного в конфигурационных файлах? )
Да и проблема с удобством решилась — привыкли и сразу стало удобно, этот аргумент, значит, тоже вычеркиваем..
Здравствуйте, AndrewVK, Вы писали:
AVK>Это всегда будет так — пользователь всегда будет добавлять свои, специфичные алгоритмы, и добавлять он их скорее всего будет не при помощи наследования от классов библиотеки.
Пользователь пускай, зачем это делать автору библиотеки? Кому нужна такая бяка?
Здравствуйте, adontz, Вы писали:
AVK>>Это всегда будет так — пользователь всегда будет добавлять свои, специфичные алгоритмы, и добавлять он их скорее всего будет не при помощи наследования от классов библиотеки.
A>Пользователь пускай, зачем это делать автору библиотеки?
А это уже не важно — как справедливо заметил Мейерс, это уже есть де факто, и бесполезно с этим бороться, тем более путем утяжеления публичных интерфейсов.
A> Кому нужна такая бяка?
Мне.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, adontz, Вы писали:
A>Если это внешний интерфейс библиотеки, в классе.
Всю библиотеку в одном классе? Смело.. )
A>Борьба идёт за внешний интерфейс библиотеки.
"Этот стон у нас песней зовется.." (с)