IDE-то е наклонена плоскост

Това са малко размисли на тема IDE-та (като Eclipse, IntelliJ и RubyMine) и редактори (като Vim, Emacs и SublimeText). Ще разкажа за един проблем с IDE-тата. Disclaimer: не смятам едните за строго по-добри от други – избора, както обикновено, зависи от контекста.

IDE-тата обикновено са оптимизирани около определен начин на решаване на проблемите. Когато искате да ги решите по различен начин, има два варианта. В първия случай IDE-то ви позволява, но поради „специфичността“ на подхода, губите част от неговите благинки. Във втория IDE-то въобще не поддържа тази възможност и тогава заобикаляте проблема отдалеч. Всичко това афектира качеството на проекта.

Илюстрация

Следва прост пример от RubyMine, от времето в което си играх с него. Проблемът вече е решен, но целта ми е да илюстрирам концептуален принцип, а не конкретен проблем.

Във версията, в която си играх за последно, имаше поддръжка на RSpec, но тя бе леко осакатена. Спекове в RSpec се дефинират така:

describe Thing do
  it "is fancy" do
    Thing.new.should be_fancy
  end

  it "looks cool" do
    Thing.new.should be_looking_cool
  end
end

RubyMine се справяше добре с пускането на тестовете и показване на резултати. Например, имаше shortcut за пускане единствено на теста, в който се намира курсора. Също, създава списък от неуспешни тестове, към които може да се навигира лесно (или да се пуснат само те). Дотук добре.

Да видим какво става, ако класът е в именовано пространство (Widget::Thing). Тогава аз (и не само) предпочитам следния код:

module Widget
  describe Thing do
    it "is fancy" do
      Thing.new.should be_fancy
    end

    it "looks cool" do
      Thing.new.should be_looking_cool
    end
  end
end

Така spec-а е поставен в самия модул. Това е напълно нормално Ruby. Предимството е, че Thing няма нужда да се квалифицира навсякъде с пълен път. Всичко работи нормално.

Освен RubyMine.

RubyMine просто нямаше поддръжа за spec-ове, написани така. Нито работеха клавишите за пускане на определен тест, нито въобще откриваше теста. Едната алтернатива бе да се пускат от терминала, което е изключително неудобно. Другата е да си направите специална задача, която да пуска този (или текущия) файл. Последното работи частично – няма нужда да ходите в терминала, но нито клавиша за „тест под курсора“, нито интерфейса за неуспешни тестове, работят.

RubyMine не е с отворен код, съответно, не може да решите този проблем. Може, обаче, да го заобиколите:

describe Widget::Thing do
  it "is fancy" do
    Widget::Thing.new.should be_fancy
  end

  it "looks cool" do
    Widget::Thing.new.should be_looking_cool
  end
end

Това работи, но всеки път трябва да квалифицирате класа с пълния път.

Първия код е очевидно по-добър, но не работи в IDE-то ви. Какво правите? Може да пускате тестове през терминала, но тогава губите част от IDE-то си. А може да изнесете describe извън модула и да квалифицирате имената с пълен път, но тогава губи кода ви. И в двата случая – лошо.

Имахме колега, работещ с RubyMine и той бе избрал втория път. От това страдахме всички. По-интересно – дори не бе осъзнал, че първият вариант е валиден. Бе пробвал да го направи по първия начин, но не бе сработило – не защото е невалидно, а защото IDE-то не го поддържа.

Проблема бе решен в следваща версия на RubyMine, но това остана като интересен урок. Решенията на въпросния колега не бяха мотивирани от кода, а на възможностите на средата му. Както и възприятието му за това кое работи и кое не.

Ами ако искахме да ползваме друга тестова библиотека, която няма поддръжа в RubyMine? Може би тя щеше да се справя по-добре, но липсата на поддръжка определено щеше да му вързва ръцете. Съответно, щеше да е по-вероятно да не я предпочете. Щеше да я вижда като нещо, което го забавя (поради липсата на tooling), докато останалите щяхме да го виждаме като нещо, което ни забързва.

Наклонената плоскост

Като програмисти, имаме навика да вървим по пътя на най-лесното съпротивление. Ако трябва да изберем между нещо, което става лесно в средата ни и нещо, което става трудно, обикновено бихме предпочели лесното. Дори трудния вариант да е „по-чист“, лесният е по-прагматичен. В крайна сметка, това също е фактор в цената на поддръжката.

Виждаме проекта през лещите на инструментите си. IDE-та са специфични. Правят някои неща лесни, но други остават трудни или почти невъзможни. Това афектира как предпочитаме да пишем код, какви инструменти използваме и дори какво смятаме за добър дизайн. Благодарение на auto-complete и class browser, сложна йерархия е много по-разбираема в Eclipse, отколкото в UltraEdit. Eclipse потребителя може да сметне за добър код нещо, което за UltraEdit потребителя е твърде сложно.

Това е „проклятието и благословията“ на IDE-тата – налагат подход. Когато този подход е подходящ за проекта, всичко е супер. Когато не е – започваме да вземаме грешни решения.

Различното в редакторите

Представете си същия проблем, но в SublimeText. RSpec плъгина е просто набор от shell скриптове и ruby файлове, които единствено пускат rspec (или rake) и извежат резултати, подходящи за Sublime. Бързично отваряте кода, добавяте нужните параметри и сте готови.

Дори да бяхте подбрали библиотека без поддръжка, може просто да копирате rspec плъгина и да го промените. Няма да е сложно и няма да отнеме много време.

В IntelliJ/RubyMine това няма как да стане. В Eclipse може, но съществената разлика е в простотата – всеки SublimeText потребител може да извърши тази задача, но колко Eclipse потребители дори знаят откъде да започнат да модифицират плъгин?

Редактори vs. IDE-та

Това значи ли, че IDE-тата не струват? Не, разбира се. Въпрос на trade-off. Някои неща стават лесно в редактори, други – в IDE-та. Това е едно от първите. Има други, които са елементарни в интегрираните среди и почти невъзможни в текстовите редактори. Автоматизиран refactoring е само един от примерите, за които се сещам.

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

Важно е да знаем кога те са породени от ограничения на IDE-то.


Бележки под линия

  • Предпочитам Vim за повечето неща, но ако трябва да пиша на Java, определено бих ползвал Eclipse (или IntelliJ). Предимствата на IDE-то в този случай са сериозни.
  • Иска ми се да мога да кажа, че тези проблеми са ограничени до Ruby. Уви, не е така. Докато бях Java програмист, имах много подобни мъки с Eclipse, Spring, Wicket и AspectJ. Често избягвахме да ползваме „по-добри“ неща заради липса на (добра) поддръжа в IDE-то.
  • Често „редакторите“ са по-гъвкави, понеже ползват стандартни command line инструменти (напр. Rake, Maven, rspec и прочее). Това ги ограничава до тяхните възможности, но пък всички редактори (Vim, Emacs, SublimeText) ги преизползват. Това напомня на „The Unix Way“. За сметка на това, няма преизползване между Java refactoring-а на Eclipse и този на IntelliJ.
  • Този аргумент има и опъка страна – IDE-тата могат да ви тласкат и към добри практики. Например, много по-лесно ще се научите на refactoring на малки стъпки в IDE (където има поддръжка), отколкото във Vim (където няма). Аз, например, се научих с Eclipse.

11 thoughts on “IDE-то е наклонена плоскост

  1. LightTable ми е много интересен, най-вече заради добрата Clojure поддръжка. Личи му, че е още млад и липсват разни работи. Имам нужда да задълбая в него (особено покрай курса по Clojure, който ще водя втория семестър).

    Причислявам го към редакторите.

  2. Интересното е, че разделението редактор vs. IDE е изцяло психологическо и наложено от маркетинга на определени компании.

    Няма техническа причина да не може различните удобства предлагани от IDE-тата да се реализират като малки инструменти, които всеки да може да ползва с любимият си текстов редактор или да навързва с други подобни инструменти. Попадал съм на един такъв опит за правене на IDE и го следя с интерес: http://pybee.org/. Като такъв инструмент бих класифицирал и напълно самостоятелният рефакторинг инструмент за питон – rope (http://rope.sourceforge.net/)

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

  3. Т.е. ако Eclipse започне да поддържа плъгини от по един-два класа и/или bash scriptа, които да зарежда с едно цъкване, ще вземе единственото предимство на редакторите – гъвкавостта? :)

    Това, което на мен не ми харесва в тази гъвкавост (и може би причина да не я добавят в Eclipse, освен, разбира се, стабилността), е че тя не непременно принадлежи в редактора – тя е за build tool-а, CI-a, някакъв post-processor, но е хубаво да може да се случва по платформено-независим начин, и дори headless. Защото когато си направиш vim-а да решава едийкойси проблем, трябва да го дадеш на всички останали от екипа. Трябва и CI системата ти да може да го използва (ако е свързано с нея, разбира се). В тоя момент вече ти трябва versioning на тези плъгини, щото иначе на половината хора в екипа и на някой нов някаква част от проекта няма да им работи, защото няма да имат инсталирани 3-4 баш скрипта, дето си си пуснал локално. И това си става съвсем отделна, ресурсоемка задача.

    А с нещо не съм съгласен – че програмистите отиват по пътя на най-ниското съпротивление. Ако беше така, нямаше да ползват git :) Програмистите често са хора, които получават удоволствие от това, че са решили сложен проблем. Може този проблем изобщо да не трябва да съществува, но на тях им харесва да го решават. Моят пример с това винаги е линукс – ще ти отнеме два дни ровене и мъки, прекомпилиране на kernel и ръчно конфигуриране в 20 файла в /etc/mainasiraina, за да си подкараш мрежовата карта и да спреш забиването като пуснеш по-интезивно I/O, но ако си от гореописания тип хора, ти ще захаресваш Linux още повече, защото си се справил с този сложен проблем. Това вътрешно задоволство от сложност заради самата сложност винаги трябва да се има предвид и при избора на редактор, всъщност :)

  4. @Божо интересна гледна точка. Ето няколко размишления.

    Да, Eclipse щеше да е една идея по-приятен ако можеше да се customize-ва дори по толкова прост начин. Впрочем, в малка част може – Run-а може да получава каквото му дадеш и прочее.

    В повечето случаи гъвкавостта наистина е в build tool-а – в моя пример, пускането на определен тест е просто параметър към rspec. Например,

    rspec --line-number 42
    пуска теста на 42 ред. RubyMine в този случай се дънеше, понеже правеше повече от build tool-а. В контраст, както Vim плъгините, така и тези за SublimeText единствено подават допълнителния параметър. Тук въпроса е по-скоро на интеграция – колкото и да е странно, SublimeText-а се интегрира по-плавно с build tool-а, понеже само го вика през command line, докато RubyMine се чупи, понеже опитва да е по-умен. Малко специфично, но това е bottom line-а в този случай.

    От друга страна, има някои неща, които просто не принадлежат на build tool-а. Например continuous testing, навигация из файловете, интеграцията с редактора, скачане от stacktrace/coverate report към съответния файл или дори малко по-сложни клавишни комбинации/макроси – всичко това е в редактора. В моите dotfiles няма нито едно нещо, което би могло да бъде в build tool-а. По мои наблюдения, когато нещо пасва в Rake, хората го слагат в Rake и го обвиват в редактора си, ако има нужда.

    Финално, съпротивлението. Това е интересна гледна точка и наистина, като програмисти обичаме да решаваме проблеми със съпротивление. Уви, обичаме да решаваме само някои проблеми със съпротивление, а не всички. Предполагам това са интересните и забавни проблеми – пипането на Eclipse може да е такъв, ако си падаш по тези неща (както пипането на Vim е за мен), но едва ли е така за всички. Да ти върна примера – ти си на Windows, а не на Linux, въпреки че там определено има съпротивление :) . Добави към това и натиска да решиш важните проблеми в deadline и съвсем спокойно мога да заявя, че вървим по пътя на по-малкото съпротивление в повечето случаи.

  5. Хубави размишления.

    За съжаление всеки tool има този проблем. В момента, в който започнеш да излизаш от рамките му получаваш проблем. От използването на малки инструменти(The Unix philosophy), ти получаваш точно това – във всеки един момент може да замениш малка част от инструментите си и да продължиш нормална работа.

    Аз съм vim user от както се помня(друг editer не съм ползвал май никога по – сериозно). И все пак ползвам ли IDE? – да ако имам възможност за дадения език! В последно време гледам, че езиците слагат малки инструменти за refactoring, autocomplete, formatting, build tool вътре в стандартната дистрибуция на езика(пример golang) и това ми харесва. За мен IDE-то обаче е задължително ако се занимаваш професионално с тая работа. Можеш да ми спориш колко по – бързо ще редактираш текст във vim отколкото аз в eclipse, но аз получавам бонуса, че не редактирам текст, а семантична част от програмата. Това е една от идеите на LightTable – нямаш файлове ами отделни функции. Аз така мисля за програмирането, когато го правя в eclipse. Не „отвори тоя файл“ ами „намери ми тоя class (Ctrl + Shift + T)“. Не е „сега ще направя променлива от тоя ред“ ами „ще дам име на тоя expression ( Ctrl + l )“. Ти казваш, че IDE-то ти налага (лош?) начин на мислене, което го няма в едитора – аз мисля точно обратното!

    За съжаление тия неща никога не работят перфектно във vim(можеш да ги измъчиш в някои случаи), защото той просто не прави синтактичен анализ на ниво проект(може за един файл да го накараш) – там няма такова нещо като expression(и не text objects не е същото). Ако езика няма IDE ми е приятно във vim(пример puppet + ruby + rspec), но просто не е същото.

    В крайна сметка според мен повечето себе уважаващи се програмисти ползват и двете. За последния проект на java ползвах IntelliJ(защото всички в екипа това ползваха, а не eclipse) и vim за редактиране на cucumber feature файловете и съм много доволен!

    Този пост е писан във vim, с помощта на приставка във firefox. Mail-а също си пиша във vim, а не във IDE-то :)

  6. @Николай две малки бележки.

    Първо – и не мога да спра да подчертавам това – малко езици имат IDE-та, които са на такова ниво, за което ти говориш. Java например, предполагам и C#. В повечето други, feature-ите на добре тунингован Vim (или на почти vanilla SublimeText) са сравними с тези на „IDE“-то. Има tradeoff-и, но са в един ballpark. Разликата идва от колко customizable е редактора.

    Второ, не мога да се съглася с това изречение: „За мен IDE-то обаче е задължително ако се занимаваш професионално с тая работа.“. Мога да дам немалко контрапримери в лицето на известни програмисти или хора с успешен бизнес.

  7. 1) Вярно :). Може би не стана ясно от това, което съм написал. И аз ползвам vim за някои езици, защото просто няма по – добър tool support – IDE-то там не става.

    2) Хмм. Това може би е малко пресилено наистина. Все пак и другото мога спокойно да го кажа „За мен обаче добър едитор е задължителен ако се занимаваш професионално с тая работа.“ Мда примери винаги ще има. Интересно е да може би да се направи статистика – каква част от хората, занимаващи се с java и имат достъп до добро IDE работят на нормален editor. Може би това обаче се отплесва от причината за твоя пост :)

  8. @Николай

    аз получавам бонуса, че не редактирам текст, а семантична част от програмата. Това е една от идеите на LightTable – нямаш файлове ами отделни функции. Аз така мисля за програмирането, когато го правя в eclipse. Не „отвори тоя файл“ ами „намери ми тоя class (Ctrl + Shift + T)“.

    Искам да ти обърна внимание, че това предимство си има и тъмна страна (винаги има!). Много е лесно да спреш тотално да мислиш за организацията на кода и това къде живеят дадени класове и методи. Попадал съм на такива мърляви изпълнения – класове в грешни пакети/директории, никакво контролиране на зависимостите (всеки вика всеки), грешки в имена на класове и методи, които живеят с години заради autocomplete/autoimport услугите на IDE-тата, че ми е идвало да си купя пистолет. И всичкото това почти неизменно е причинено от сляпо (продуктивно?) цъкане по менюта в IDE-то.

    <дзен> Често има стойност нещата да стават по-бавно, за да можем да ги осъзнаем, да помислим за тях и да им се насладим напълно. Няма нужда всичко да се случва веднага.

  9. А какъв е проблема да си ползваш Widget::Thing и described_class @ spec?

  10. @Емо: Проблем няма, но тая индирекция на мен не ми харесва. Има смисъл, когато ползваш споделени примери (shared examples), но когато знаеш в кой тест си, директното име би било по-хубаво. Т.е., първо предпочитам Thing, после Widget::Thing и чак накрая described_class.

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *