Магистр ДонНТУ Лащенко Андрей Владимирович

Лащенко Андрей Владимирович

Факультет компьютерных наук и технологий
Кафедра систем искуственного интеллекта
Специальность: «Системы искуственного интеллекта»

Тема выпускной работы: «Разработка методов и алгоритмов контурной сегментации в задачах поиска однородных объектов на изображении»

Научный руководитель: д.ф.-м.н., проф. Владислав Юрьевич Шелепов


Есть два способа создания дизайна программы. Один из них, это сделать его настолько простым, что в нем, очевидно, не будет недостатков. Другой способ — сделать его настолько запутанным, что в нем не будет очевидных недостатков.

Чарльз Энтони Ричард Хоар






На данный момент я серьезно занимаюсь программированием более 6 лет. Я хотел бы расказать о том, с какими технологиями и проектами мне приходилось работать.


 Язык программирования C++ и Qt


C++ был моим основным языком программирования с 2005 года. Еще во время учебы я заинтересовался Qt.

Мой серьезный опыт в программировании начинается с весны 2008 года, когда мне предложили поработать в отделе распознавания речевых образов научно-исследовательского института проблем искусственного интеллекта. Как раз в то время в отделе начинали задумываться о переходе на Linux, в связи с этим необходимо было использовать библиотеки, позволяющие писать кросплатформенные приложения. В отделе была популярна WxWidgets, однако симпатии у меня эта библиотека не вызывала, поэтому я продолжил использовать свою любимую связку C++ и Qt, а для работы со звуком использовалась OpenAL. Проект, над которым я работал, носил название "Разработка автоматизированной компьютерной системы фоноскопической экспертизы цифровых фонограмм". Мной были разработаны, модифицированы и реализованы различные алгоритмы цифровой обработки речи. Проводились исследования в области автоматической сегментации речевого сигнала. Велись работы над обнаружением монтажа в цифровом сигнале. Много внимания было уделено выделению фонем из спектра речевого сигнала.



Примерно в это же время у меня появился первый телефон с ОС Symbian, а вместе с ним и опыт написания приложений для мобильных устройств с использованием Qt и C++. Мне было просто интересно писать приложения для взаимодействия с пользователем посредством сенсорного экрана.

В данное время я продолжаю использовать Qt/C++, но в гораздо меньшей степени, например, для создания приложений, позволяющих более наглядно и красиво отобразить файлы в некоторых специфических текстовых форматах.


 Язык программирования Python


В продолжение повествования об исследовательской деятельности, хочется отметить Python. Это очень простой и выразительный язык, для которого существует множество исследовательских библиотек. Я использую в свободное время scikit-learn, scikit-image, scikit-audiolabs, scipy, numpy, matplotlib. В настоящее время доступно множество замечательных книг, описывающих работу с этими библиотеками. Стоит отметить, что в данное время уровень языка и наличие таких библиотек позволяет рассматривать это все как замену Matlab, о чем ведется много дискуссий.


 Язык программирования Java


Впервые интерес к Java у меня появился где-то в 2009 году. В 2011 году я получил сертификат "Oracle Certified Professional, Java SE 6 Programmer".

Коммерческий опыт начался с 2010 года в Exadel, где я занимался написанием web UI (с использованием GWT), валидаторов и заглушек для серверной части в рамках глобального проекта MaxTrad Online Trade Services.

Затем я был вовлечен в разработку ПО для ресиверов цифрового телевидения компании DirecTV. Java действительно работает везде, даже на встраиваемых системах. Попробую описать различные уровни приложений и их взаимодействие в случае встраиваемых систем. На низком уровне используется C/C++ и bash script, далее, через JNI, все передается на уровень, на котором начинается использование Java, вплоть до верхнего уровня UI. Использование Bash Script оправдано во многих случаях при работе с UNIX-подобными системами. В моем случае была необходимость проводить различные манипуляции с файлами и дисковым пространством еще на этапе загрузки ОС, в то время, когда JVM еще не загружена. Это были основные инструменты при разработке системы плагинов, обработки медиа-данных и написания UI. Кроме того было много рефакторинга.

Как Java разработчик я не мог не попробовать писать приложения для Android. Мне доставляло удовольствие разбираться с системой. Было интересно заниматься обработкой медиа данных, полученных с камеры и микрофона устройства. Отдельно хочется отметить, что в данное время OpenCV очень легко и приятно использовать при разработке приложений для Android. Когда мне понадобился сканер различных штрих-кодов, я рассматривал ZXing, написанный на Java, и ZBar, написанный на C, для которого я делал сборку и "обертки" для удобного использования в Java. Не знаю как сейчас, но в то время ZXing не мог справиться со многими кодами, в отличии от ZBar - https://github.com/lashchenko/AZbar/wiki.

Весной 2012 года я начал работать в компании Luxoft над серверной частью одного из проектов Deutche Bank, связанного с проведением сделок на финансовых рынках.
В этом проекте мы начали понемногу использовать Scala, вместо JBoss Drools flow и Drools rules, а затем появились еще несколько проектов, в которых Scala стала основным языком.


 Язык программирования Scala


Так получилось, что практически весь последний год я использовал Scala в 90% случаев. Впечатления исключительно положительные. Мне бы хотелось кратко, насколько это возможно, написать про этот замечательный язык программирования.


Развитие языков Java и C++ существенно замедлилось, и программисты, стремящиеся использовать самые современные технологии, обратили свои взоры на другие языки. Scala - весьма привлекательный выбор. Вероятно, это самый привлекательный выбор для программистов, стремящихся вырваться за рамки Java или C++. Scala имеет выразительный синтаксис, который выглядит весьма свежо после приевшихся шаблонов Java. Программы на этом языке выполняются под управлением виртуальной машины Java, что открывает доступ к огромному количеству библиотек и инструментов. Он поддерживает функциональный стиль программирования, не отказываясь при этом от объектно-ориентированного стиля, давая возможность осваивать новые парадигмы постепенно. Интерпретатор дает возможность быстро опробовать свои идеи, что превращает изучение Scala в весьма увлекательное занятие. Наконец, язык Scala является статически типизированным языком, что дает компилятору возможность находить ошибки, а вам не тратить время на их поиск в работающей программе.

Области применения Scala

Некоторые крупные компании использующие Scala Scala используется многими крупными компаниями, такими как Twitter, LinkedIn, SONY, IBM, Deutche Bank, UBS, Foursquare, Amazon, NASA, Autodesk, Siemens. Подробнее можно почитать в разделе Scala in the Enterprise. Поскольку Scala является языком программирования общего назначения, она может успешно применяться в самых разнообразных областях, например при создании:

Выразительность Scala

Рассмотрим типичный пример кода, написанного на Java.


    public class Person implements Serializable {
    private final String firstName;
    private final String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public Person withFirstName(String firstName) {
        return new Person(firstName, lastName);
    }

    public Person withLastName(String lastName) {
        return new Person(firstName, lastName);
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Person person = (Person) o;
        if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) {
            return false;
        }
        if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) {
            return false;
        }
        return true;
    }

    public int hashCode() {
        int result = firstName != null ? firstName.hashCode() : 0;
        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
        return result;
    }

    public String toString() {
        return "Person(" + firstName + "," + lastName + ")";
    }

Напишем несколько строк, показывающих, как использовать этот класс:
Person mr = new Person("Bob", "Dobbelina");
Person miss = new Person("Roberta", "MacSweeney");
Person mrs = miss.withLastName(mr.getLastName());

А теперь перепишем класс Person, используя Scala.
case class Person(firstName: String, lastName: String)
Это все. Мы можем использовать этот класс так же как в Java, даже более компактно:
val mr = Person("Bob", "Dobbelina")
val miss = Person("Roberta", "MacSweeney")
val mrs = miss copy (lastName = mr.lastName)

Если необходимо иметь JavaBeans методы доступа к полям firstName и lastName - можно сгенерировать их автоматически, используя аннотацию @BeanProperty, как показано ниже:
case class Person(@BeanProperty firstName: String, @BeanProperty lastName: String)

Императивная и функциональная парадигма программирования в Scala

На Scala можно писать в императивном стиле:

def formatPersons(people: List[Person]): String = {
    val result = new StringBuilder();
    for (i <- 0 until people.size) {
        val firstName = people(i).firstName
        if (firstName != "test") {
            result.append(firstName)
            if (i < people.size - 1) {
                result.append(", ")
            }
        }
    }
    return result.toString
}
Но, наличие мощной системы вывода типов и возможность использовать функциональный подход позволяют переписать предыдущий пример следующим образом (заодно исправляя допущенную ранее ошибку):
def formatPersons(people: List[Person]) = people map (_.firstName) filter (_ != "test") mkString ", "
Приведу несколько примеров из статьи 10 Scala One Liners to Impress Your Friends, чтобы показать красоту и выразительность функционального подхода.
  1. Обработка списков:
    // Умножение каждого элемента списка на 2:
    (1 to 10) map { _ * 2 }
    
    // Подсчет суммы всех чисел в списке:
    (1 to 1000).reduceLeft( _ + _ )
    (1 to 1000).sum
    
    // Разбиение списка по заданному критерию:
    val (passed, failed) = List(49, 58, 76, 82, 88, 90) partition ( _ > 60 )
    
    // Поиск минимума в списке
    List(14, 35, -7, 46, 98).reduceLeft ( _ min _ )
    List(14, 35, -7, 46, 98).min
    
    // Поиск максимума в списке
    List(14, 35, -7, 46, 98).reduceLeft ( _ max _ )
    List(14, 35, -7, 46, 98).max
    
  2. Параллельная обработка данных:
    val result = dataList.par.map(line => processItem(line))
  3. Проверка вхождения подстрок в строке:
    val wordList = List("scala", "akka", "play framework", "sbt", "typesafe")
    val tweet = "This is an example tweet talking about scala and sbt."
    
    (wordList.foldLeft(false)( _ || tweet.contains(_) ))
    wordList.exists(tweet.contains)
  4. Чтение текста из файла:
    val fileText = io.Source.fromFile("data.txt").mkString
    val fileLines = io.Source.fromFile("data.txt").getLines.toList
  5. Получение и разбор XML от web-сервиса:
    val results = XML.load("http://search.twitter.com/search.atom?gitq=scala")

Что еще есть в Scala

Ниже приведен небольшой список ссылок на хорошее описание некоторых возможностей Scala, которых нет в Java.

Параллельные вычисления в Scala

Акторы представляют собой механизм параллельных вычислений, альтернативный традиционным механизмам на основе блокировок. Отсутствие блокировок и совместно используемых данных в акторах упрощает разработку программ и позволяет не опасаться взаимоблокировок и состояний гонки за ресурсами.
Ранее Scala предоставляла простейшую реализацию акторов. Более совершенные реализации акторов доступны на сторонних ресурсах, самым известным из которых является проект Akka. Начиная с версии 2.10, в Scala была включена поддержка акторов Akka Actors.
Приведем классический HelloWorld, написанный на Scala с использованием акторов, с сайта akka.io.

case class Greeting(who: String)
 
class GreetingActor extends Actor with ActorLogging {
  def receive = {
    case Greeting(who) ⇒ log.info("Hello " + who)
  }
}
 
val system = ActorSystem("MySystem")
val greeter = system.actorOf(Props[GreetingActor], name = "greeter")
greeter ! Greeting("Charlie Parker")
Более серьезный пример параллельного вычисления числа π можно посмотреть в разделе Getting Started Tutorial, а также почитать про Dataflow Concurrency, Parallel collections и Futures and Promises.

Динамика изменения количества вакансий на Scala

Стоит отметить, что в последнее время интерес к Scala сильно возрос и продолжает расти, причем не только в академических кругах.

Scala Job Trends

Книги, презентации, статьи и ресурсы про Scala

  1. Alex Payne. Building Distributed Systems in Scala.
  2. João Bernardino. Selling Scala to your boss.
  3. Александр Казачёнок. Зачем нужна Scala?
  4. Community-driven documentation for Scala.
  5. Akka documentation.
  6. David Pollak. Beginning Scala.
  7. Venkat Subramaniam. Programming Scala: Tackle Multi-Core Complexity on the Java Virtual Machine.
  8. Cay S. Horstmann. Scala for the Impatient.
  9. Martin Odersky, Lex Spoon, Bill Venners. Programming in Scala.
  10. Samples of Scala and Java code where Scala code looks simpler/has fewer lines?
  11. Why Learn Scala in 2013?