Про использование функционального стиля в ежедневном C#. Убираем простое дублирование кода
Современное ПО для создания другого ПО достигло огромных высот. Хоть и похоже на тавтологию но это правда. После появления Java и IntelijIdea а так же C# нам как программистам очень мало рутинной работы осталось делать руками. Даже рефакторинги оказались автоматизированными. Казалось — бы программисту осталось только напрягать голову для создания прекрасных дизайнов и алгоритмов. Имхо осталась одна проблема идущая с незапамятных времен и до сих пор не решенная в мейнстриме и языками программирования и средами разработки. Эта проблема — дублирование кода. Вот тут нам и помогает фп.
Сразу оговорюсь что я буду описывать именно C# хотя наверное идеи можно перетащить и в другой яп.
Траи и кетчи, а также юзинги и другие локи.
Очень часто мне встречается подобный код
void ReadSomeImpotantDataFromXml() { lock(fileName) { using(XmlReader reader = XmlReader.Create(fileName)) { while(reader.Read()) { try { //do some stuff 1 } catch(InvalidReadException ex) { //do dome stuff 2 } } } } }
вполне нормально быстрое и потоко — безопасное чтение из xml. Кода оно одно — нет проблем и все хорошо, но вот если его надо использовать в нескольких местах с разной логикой обработки в do some stuff 1 и do some stuff 2 вот тут и начинаются проблемы. Кож естественно расплывается по проекту (по нескольким?). И вот тут выходит класс который позволяет нам читать Xml в 2раза быстрее чем XmlReader. Вы четко понимаете что надо перезжать. Вот только как? Искать эти фрагменты во всех проектах — уму не постижимо. Что же делать? Давайте устроим маленький рефакторинг :)
Action<Action,Action> initFunction = (doSomeStuff1,doSomeStuff2,fileName)=> { lock(fileName) { using(XmlReader reader = XmlReader.Create(fileName)) { while(reader.Read()) { try { doSomeStuff1(reader); } catch(InvalidReadException ex) { doSomeStuff2(ex); } } } } }; void ReadSomeImpotantDataFromXml() { initFunction(reader=> { //do some stuff 1 }, ex=> { //do some stuff 2 }, fileName); }
В общем-то теперь мы можем использовать initFunction где угодно и при изменение XmlReader на XmlReader2 сделать нам это придется только в 1м месте.
Предыдущий пример показал идею известную давно, но практически его применить очень трудно. Не везде процесс инициализации и освобождения ресурсов так прост. Точнее он нигде не бывает так прост и так одинаков.