Чи є майбутнє у керованої моделлю розробки програмного забезпечення

Давненько не писав. Часто виникає бажання щось написати, але потім якось руки не доходять. Аж раптом нещодавно трапилась мені на очі презентація шановного Джона ден Хаана під назвою «Чому у керованої моделлю розробки програмного забезпечення немає майбутнього» (Why there is no future for model driven development). Оскільки я палкий прихильник розробки програмного забезпечення, керованої моделлю, не можу не відреагувати. Свою думку я йому коротко висловив на сайті, а тепер вирішив трохи детальніше розміркувати.
Почнімо з визначення. Отже розробка програмного забезпечення, керована моделлю (РКМ) – це методологія розробки програмного забезпечення (ПЗ), що спрямована на використання моделей ПЗ як основних продуктів розробки та генерування на їх основі інших робочих продуктів, у тому числі і вихідного коду, наприклад на Java або C++. Як і більшість понять у галузі ПЗ, це поняття запозичене із більш традиційних інженерних дисциплін, хоча там на керованості моделлю так явно не наголошують, оскільки використання моделей є загальноприйнятим. Ніхто навіть і уявити собі не може конструювання такої будівлі як Московський Міст у Києві чи літак «Мрія» без попередньої побудови великої кількості різноманітних спеціалізованих моделей. Моделі допомагають зрозуміти складні завдання та їх потенційні розв’язки через абстракцію. Однак у галузі розробки ПЗ моделювання аж ніяк не набуло широкого впровадження. Не будемо тут намагатися аналізувати причини, це тема окремого посту, а перейдемо відразу до демонстрації того, що РКМ має майбутнє.
Не вдаючись до історії постійного підвищення рівня абстракції мов програмування, відразу перерахуємо фундаментальні принципи програмної інженерії та покажемо як РКМ відповідає цим принципам: строгість та формальність, розділення відповідальності, модульність, абстракція, передбачення змін.
Строгість та формальність. Розробка програмного забезпечення є творчою діяльністю. У будь якій творчій діяльності є схильність до неточності. Строгість та формальність необхідне доповнення будь-якої інженерної діяльності. Тільки так можливо контролювати вартість та якість продуктів на виході такої діяльності. Моделювання ПЗ, використовуючи формальні мови, зі строго заданими синтаксисом та семантикою безумовно відповідає цьому принципу. Звісно, тут не йдеться про архітектуру, намальовану маркером на дошці, така модель корисна хіба що для обговорення проектних рішень.
Розділення відповідальності. Один з найголовніших принципів інженерії взагалі та інженерії ПЗ зокрема. Розділення відповідальності – це спрощення єдиного монолітного розв’язання завдання шляхом поділу на взаємодіючі розв’язання під-завдань. Моделювання різних аспектів ПЗ, таких як бізнес-логіка або архітектура, за допомогою різних, предметно-орієнтованих мов програмування (DSLs) є реалізацією цього принципу. Особливу вагу для бізнесу мають предметно-орієнтовані мови, призначені для опису конкретної галузі в якій працюватиме застосування. Наприклад, мови для опису управляння страховими полісами, бізнес процесів, алгоритмів розрахунку статистики успішності студентів і т.д. Програму, написану такою мовою зможе читати бізнес експерт, а програму мовою Java – ні.
Модульність. Цей принцип є окремим випадком попереднього. Суть його полягає у розбитті системи на простіші частини, що називаються модулями, компонентами, сервісами і т.д. Перераховані назви є, безумовно, абстракціями, створеними для реалізації принципу модульності. Однак ми не обмежені лише цими абстракціями у побудові ПЗ! Ми можемо послуговуватися, формально визначивши, такими абстракціями як компонент, процес, замикання, виключення, повідомлення, синхронізація, з’єднувач, двигун, крило літака, контролер, гамбургер, страховий поліс, множина яких обмежена лише нашою фантазією! Усі вони є частинками певного застосування, а моделювання ПЗ з їх використанням є реалізацією принципу модульності.
Абстракція. Принцип не потребує коментування. Відзначимо, що усе ПЗ є абстракцією. Абстракція дозволяє нам створювати складні системи. Абстракція подарувала нам поняття класу, об’єкту, події, функції, бібліотеки, тощо. Розробка ПЗ є складною. ПЗ є найскладнішим продуктом, що створює людина. Якщо задатися запитанням: а скільки інженерів-механіків я знаю? А скільки інженерів програмістів? Думаю, останніх у декілька разів більше. Гадаю, саме робота на надто низькому рівні абстракції змушує компанії наймати усе більше інженерів з ПЗ та виставляти захмарні ціни за розроблення та супроводження ПЗ. РКМ дає можливість підвищувати рівень абстракції та створювати нові абстракції, що краще відповідають потребам зацікавлених у розробці сторін.
Передбачення змін наголошує на тому, що необхідно передбачати та створювати зручні умови для внесення змін у ПЗ. Як правило, реалізацію цього принципу забезпечують модульність та розділення відповідальності. Якщо різні аспекти системи модельовані окремо, то можна легко змінювати окремо від інших аспектів бізнес-логіку, архітектуру, базову абстрактну машину (мови програмування, операційні системи, проміжне ПЗ, бази даних, тощо). Тобто РКМ надає інструменти для ефективної реалізації принципу передбачення змін.
Звісно, РКМ не є срібною кулею, гадаю такої кулі не буде винайдено. Однак, на мою думку, це закономірний рух уперед і дозрівання розробки програмного забезпечення до інженерної дисципліни. Автор коментованої доповіді відзначив, що моделювання має стосуватися не лише конструювання ПЗ, а й інших фаз розробки, особливо збору вимог, та розгортання. З цим важко не погодитися, тому правильніший термін був би не розробка, керована моделлю, а інженерія ПЗ, керована моделлю. Аби така інженерія стала реальністю, необхідно ще дуже багато наукових досліджень та практичної роботи.
Отже, чи є майбутнє у інженерії ПЗ, керованої моделлю? Судячи з усього так, інакше немає майбутнього у ПЗ як такого.

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

Чи унікальність компонентів ПЗ є причиною його складності?

Я часто на своїх лекціях розповідаю студентам, що програмне забезпечення є найскладнішим інженерним творінням людини. Я, звісно, досі у цьому переконаний, але після декількох тривалих дискусій зі своїм студентом-дипломником похитнувся мій основний аргумент: у програмного забезпечення усі компоненти унікальні. Я завзято пояснював, що якщо з’являються два однакові шматки коду, то їх виносять у окрему підпрограму, залишаючи тільки виклик на старому місці. У той час електричний ланцюг може складатися з багатьох компонентів, що мають однакову функціональність: транзистори, резистори, конденсатори. Але чи доцільна така аналогія? Мабуть, коли мова заходить про компонент та про екземпляр компонента, це майже у всіх викликає замішання. І тут порівняння підпрограми з транзистором вкрай невдале, тому, що підпрограма є компонентом, а ось транзистор у мікросхемі є екземпляром компонента. Навряд чи хтось прагнутиме дублювати специфікацію транзистора, яка репрезентує абстрактне поняття компонента-транзистора. В свою чергу підпрограма багато разів ініціюється комп’ютером, який в залежності від виконуваної підпрограми-специфікації “прикидається” різними екземплярами компонентів. Насмілюся зробити висновок, що самі по собі компоненти унікальні в усіх інженерних галузях. Напевно замість згаданого аргументу слід говорити про те, що компонентів (“класів” компонентів) у програмному забезпеченні набагато більше ніж у інших творіннях людини, плюс до всього, кожен екземпляр компоненту може бути у величезній кількості станів. Можна сказати, що транзистор, у принципі, може знаходитись взагалі у нескінченній кількості станів, проте вони обумовлені законами фізики, а стани програмного забезпечення цілком визначають люди. А це вкрай складно.

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

C# vs JavaScript for Selenium tests

A few weeks ago I had a choice to be made and this choice was not easy for me. Here I would like to share my decision and some reasoning behind. I have decided to add some automated GUI testing to the project I am working on. This is a web application and therefore, the choice of the testing tool was simple – Selenium. However, I could not decide which language to use for coding the tests and testing framework. The thing is that I am currently bilingual guy (as probably every non-Node web developer) and I regularly use both C# and JavaScript. So I started coding first tests and inception of the test framework in both. After few days of coding using each language, I have finally chosen C# over JavaScript. Let me tell why and probably my reasoning will help someone else to make a decision.

I have started with JavaScript (Node, Jasmine, WebDriverJs, VS Code). Well, because:

  • Traditionally people write tests in scripting languages, which should add to the productivity and code simplicity
  • Node is true cross platform technology and if needed I would be able to run tests on any platform I like
  • I wanted to learn how to code for Node (doing modules and stuff)

At first, everything went well and smoothly, but then problems started to creep in. The root of these problems was JavaScript’s Selenium library asynchronous nature while tests are synchronous by nature. Test steps must execute sequentially because order matters. Perform “Save” button click before the form is filled and the test is miserably failed. Here are the problems:

  • Whole WebDriverJS API is asynchronous and every command results in a promise! Promise! Well, they are meant to be a simplification of callbacks, but they are still callbacks and for a sequential guy like me, haveing a promise after every API call is too much. To simulate synchronous test execution they use the ControlFlow library, which implicitly synchronizes asynchronous actions, making it so you only have to register a promise callback when you want to catch an error or access a return value. The brain just explodes. But it is just testing! It should be simple to be valuable. Resulted code with promises just promised to become maintenance nightmare;

  • Sometimes tests did not work as expected and I had to debug. You know, just put a breakpoint in the place where some call to web driver API happens. Like here, say, right before clicking the button:

But you know what? When execution stops at the breakpoint it is basically the middle of registration of callbacks. You are stopped even before Selenium started to search for “inputEmail”! I just can’t imagine where to put a breakpoint to have the test stop right before clicking the button (probably there is some way to do it but I don’t know it)

  • In the test itself, I did not want to use any variables for simplicity sake. So that business analyst or QA guy could easily understand what happens in the test. However because of
    promises I just had to introduce a variable and complexity, because there was no way to ensure that test assertion happened in the very end of the test:

While the code is probably not very complex, but it is definitely not for non-programmers.

  • Since Javascript is dynamic and WebDriverJS API is also dynamic, while coding you should constantly look at documentation or run debugger to see what kind of methods are available and how to call them correctly

After some fight, I gave up and started to do the same with C#. Wow! It was a just different world, all these problems were gone. Static typing gave fantastic auto-completion, debugging was just great! I could stop the test at any place and then go through it step by step observing the effects in the browser. Because there was no need to deal with promises while asserting, I was able to write test without variables:

Conclusion: sometimes your language and its library are not suitable for the task. Although I really like JavaScript (good parts) and it shines in the browser it turned out it is not the best option for doing test automation. Did I discover Atwood’s Law break? 🙂

Atwood’s Law: any application that can be written in JavaScript, will eventually be written in JavaScript.

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail