Мой open source велосипед

    “Воин не бросит начатое.”
    Мастер Шифу, м.ф. Кунг-фу Панда


    Можно рассматривать этот топик не как технический, а как художественный. Тут не будет кусков кода, диаграмм классов и прочей ерунды. Будет история одного java open source проекта, который я разрабатываю уже около года.

    Начало


    Все началось, когда я был на четвертом курсе одного провинциального российского университета. С семестра, о котором ходили легенды на моей специальности, как о “семестре-убийце“ с его 55-ю лабораторными работами по графике, компиляторам и вычислительной математике (далее ВМ).

    Когда в начале семестра думаешь о предстоящей большой и скучной (а в университетах как правило, все скучно) работе, не редко начинают опускаться руки. К счастью, у меня уже был проверенный временем рецепт “бесконечного энутизиазма”. Смысл его заключался в “бесконечном познании неизвестного” (с) Стругацкие, Понедельник начинается в субботу. Проще говоря, я каждый раз старался хоть как то извратить стандартный учебный процесс, чтобы он стал хоть немного интереснее для меня. Было испробовано большое количество способов — Linux на рабочей машине (с драйверами от ATI), непопулярные в университетских кругах языки (читай не С# и C++) и среды разработки (читай не VS2008), баг-трекеры для заданий, локальные репозитории кода для лабораторных и т.д.

    Тогда я и решил начать писать свой open source проект, представляющий собой агрегацию лабораторных работ по курсу ВМ в виде java библиотеки c прозрачным и привычными для java-программистов API.

    Я создал проект на Google Code, придумал название библиоткеи и работа началась. Каждая следующая лабораторная по курсу ВМ представляла собой пачку коммитов в репозиторий библиотеки. Это было что-то новое для меня и помогало мне поддерживать энтузиазм на протяжении всего курса.

    По окончанию курса la4j (Linear Algebra for Java) доросла до версии 0.0.7 и уже умела работать с векторами и матрицами, решать системы линейных уравнений 6-ю различными способами и находить собственные числа и вектора матриц.

    Середина


    После окончания курса ВМ я почти не занимался проектом, курс кончился — энтузиазм иссяк. Все изменилось, когда начался новый курс — Шаблоны проектирования.

    Этот курс меня невероятно заинтересовал, я даже начал писать об этом цикл статей на Хабрахабре. Но главное тут то, что я осознал все ошибки, которые когда-то совершил в la4j. Терпеть этого я не мог и вооружившись удобными инструментами рефакторинга Eclipse я начал кромсать код. Так получилась версия 0.1.0. Версия, которую уже не стыдно было кому-то показать. Она имела приятный ООП дизайн, небольшой но достаточный функционал. А самое главное — это был результат достаточно большой работы от которой я чувствовал удовлетворение.

    Не могу сказать, что до этого этапа я позиционировал la4j как open source проект. Я воспринимал это как свое хобби, как площадку для оттачивания своих знаний и умений. Я просто делал это just for fun.

    Потом на какое-то время я снова позабыл про la4j и начал усиленно заниматься рабочими делами, совмещая учебу и работу. Волею судьбы я стал заниматься производительность Java платформы на работе и этот факт заставил меня по-новому взглянуть на вычислительные алгоритмы внутри la4j.

    Я попытался применить полученный опыт performance анализа и оптимизаций в la4j. Так родилась статья “История одной оптимизации”, которая вызвала у хабрапользователей большой интерес к моему проекту. В тот момент я получил большое количество отзывов, а самое главное — предложений помощи. Несколько человек изъявили желание помочь мне дальше развивать проект.

    Тогда мне казалось, что сейчас все изменится. Люди начнут писать код и полетит куча коммитов в мой репозиторий. Но этого не произошло.

    Как минимум пару человек я добавил в проект, рассказал про дальнейшие планы и даже повесил issue на каждого из них с примерной задачей. Сам же я с нетерпением ждал реакции новых участников. К сожалению, так и не дождался. Люди пропали, проект я решил заморозить на неопределенный срок.

    Потом, я закончил университет и устроился на постоянную работу. Скажу лишь, что работать мне нравилось намного больше чем учиться. У меня была куча свободного времени, которое я тратил впустую, пытаясь отдохнуть от защиты диплома и марафона длиною в 5 лет.

    В сентябре, все студенты начинаю учиться и у меня как у собаки Павлова сработал условный рефлекс — нужно писать лабораторные, учить функциональный анализ и т.п. Тогда я вспомнил про la4j и решил, что должен ее закончить. Закончить не потому, что «решение систем ЛУ — очень важная и актуальная проблема современности», а просто потому что, я когда то это начал и не довел до конца.

    Первым делом я перевел проект на Maven, и начал писать тесты, решив воспользоваться методологией TDD. Как оказалось, мой выбор был удачным — во первых, видно прогресс, во-вторых, ты чувствуешь когда продукт готов к релизу.

    Я полностью пересмотрел всю архитектуру, переписал большое количество кода и написал новый. Добавил функционал (разреженные матрицы, разложения, ввод/вывод и т.д.). Я даже исправил несколько багов, которые я не мог заметить без модульного тестирования.

    И …

    Почти конец


    Несколько дней назад, я закончил работу над версией 0.2.0. Было проделано очень много работы, принято много технических и не-очень решений, спроектировано и реализовано 55 классов, написано 6700 строк кода и около 80 jUnit тестов. Надеюсь мой труд не пропадет зря, и станет еще одним удобным инструментом в портфеле любого java-разработчика.

    Конец


    Очень прошу тебя, читатель. Прежде чем писать комментарий, обрати внимание на список готовых вопросов и ответов.

    В: “На Java никто вычисления не пишет, закопать!”
    О: “Пишут. Более того, еще и не хотят использовать обертки над BLAS из за привязки к нативной платформе”.

    В: “Есть же JAMA, зачем еще один велосипед?”
    О: а) Потому что он свой. б) JAMA не поддерживает разреженые матрицы. в) JAMA не поддерживает ввод/выввод. в) у JAMA ужасный API. г) у JAMA ужасная производительность.

    Ресурсы



    UPD: На днях стала доступна версия 0.4.0 (03.06.2013)

    UPD: Тихо и незаметно вышла версия 0.4.5 (02.10.2013)
    Поделиться публикацией

    Похожие публикации

    Комментарии 30
      +3
      Спасибо. Отличная статья и отличная библиотека. Добавлю в закладки.
        0
        Спасибо :)
        +4
        Рефлекс как у собаки Павлова — хорошо сказано. Который год думаю «выйду в отпуск, появится время, допишу свой проект». И вот наступает долгожданный, какой там проект — отдыхать!
          +8
          Отличная история, спасибо.
          Однако это замечание

          > Кроме того, любая критика без ссылки на собственный open source проект восприниматься не будет

          весьма подпортило впечатление. Критика, сопровождаемая аргументами и обоснованиями, очень ценна, и не важно, от кого она исходит. Лучше получить к ней в нагрузку необоснованные нападки и проигнорировать их, чем не получить ничего.
            +1
            Может быть зря перестраховался от агресивно-настроенной публики Хабра. Может быть вы и правы, сейчас уберу.
              0
              И сразу вопрос:
              зачем класс объявляется аж так: public class Complex extends Object?
              extends Object явно лишнее и не способствует быстрому чтению и пониманию
                0
                Этот класс — открытый проект, я просто его включил в la4j.

                Вот хедер же:

                /**
                * Complex implements a complex number and defines complex
                * arithmetic and mathematical functions
                * Last Updated February 27, 2001
                * Copyright 1997-2001
                * @version 1.0
                * @author Andrew G. Bennett
                */
                  0
                  имя автора мне ничего не сказало, так как Вашего не знаю :) может это и Вы :) вот ссылка на проект было бы хорошо…
                    0
                    Ссылки никакой нет, этот человек просто где-то выложил свой клласс. Я даже не помню где его скачал. Гдето в google «java complex class».
                  +3
                  посмотрел глубже — видимо один такой попался и я сразу на него наткнулся :)
                  а вообще код чистый, С КОММЕНТАРИЯМИ! :)
                    +4
                    Кстати сначала писал их, потом даже специально стал вырезать. Не нужны они. Нужна документация, в данном случе javadoc с сылками к теории, например в википедию.

                    А любой коментарий устаревает сразу после того, как вы напишите "//".
                      +1
                      лучше код с документацией, чем такой же но без оной. Особенно когда видишь что-то типа:

                      public void updatePrios(final MultiMap<Pair<Lang,String>,Triple<Source,Integer,Boolean>> newPrios, final int type) {

                      :)
                        +3
                        Ну что нужна документация я написал.

                        Только напишите, что это не мой код :) А то щас пост заминусуют :)
                          0
                          не Ваш не Ваш ))
                          просто знаю места, где искать 8-)
                        +2
                        Поддерживаю: код изменяется, а комментарий остается.
                0
                Спасибо.
                > непопулярные в университетских кругах языки
                А какие?

                У вас хорошая обстановка на кафедре по сравнению с моей, даже несмотря на
                «непопулярные в университетских кругах языки (читай не С# и C++) и среды разработки (читай не VS2008)».
                У нас не давали практически ничего из того, что нужно давать. Шаблоны проектирования? Ну что вы… Их даже не упоминали. Функциональное программирование? Только в виде галочки в учебном плане… Приходилось многое, очень многое изучать самому, а многие преподаватели даже тематику подсказать не могли, — некомпетентность была и остается удручающая.

                P.S. У меня тоже есть свой open-source проект. ;)
                  0
                  Я бы сказал, в моем вузе отличная обстановка на кафедре, отличные преподаватели, умные ребята. Из-за объемов материала правда учиться невсегда приятно, но это мелочи.

                  А по поводу изучать самому — уж извольте. Вы высшее образование получаете, вас никто ничему не обязан учить. Ест даже фразеологизм «Научить — невозможно, можно только научиться.» Вас этому и учат на самом деле, учать не матану, вычмату и компиляторам, а учат — учиться и в сжатые сроки, в новой среде предоставлять результат. Инженерия чо уж там :)
                    0
                    > А по поводу изучать самому — уж извольте. Вы высшее образование получаете, вас никто ничему не обязан учить.

                    Пожалуйста, спокойнее в формулировках. Свое высшее образование я получил два с половиной года назад, а сейчас и вовсе сам преподаватель.

                    А так, безотностиельно себя, — да со всем согласен.
                      +1
                      Никого не хотел обидеть и из комментария подумал что вы — студент. Прошу прощения если что.
                        0
                        Никаких обид, что вы. :)

                        Так какие еще языки вы использовали в своей учебной деятельности? Java? Может, еще что-нибудь?
                          +1
                          Университетская программа мягко говоря заточена на С++ (даже тот что managed C++/CLI) и С# и конечно все это добро должно было писаться в VS2005 а потом и 2008 + Лисп и Пролог как части курсов по ФП. Все остальное — на усмотрение студента.

                          У меня это было, что-то вроде Java, Python + PyQT + numpy, Perl, совсем чуть-чуть PHP. Были эксперименты писать на GTK/QT (на Linux) ну и конечно Mono :)
                            0
                            Список достоин уважения. Сейчас не все мои бывшие сокурсники-то готовы изучать что-то помимо стандартных C#/С++, что уж говорить о студентах… Кстати, не знаю, что вы имеете в виду под «заточкой на С++», — сейчас я жалею, что ФП у нас толком не было, потому что для многих своих университетских программ я бы выбрал Haskell. Впрочем, и на «плюсах» неплохо все получалось, но считаю, что изучать новые языки, средства и технологии, надо. Раз в год осваивать новый язык, — очень хорошо, но можно и раз в полгода, не повредит. С другой стороны, кроме языков программирования есть еще огромный пласт знаний, — та же автоматизация (сборка, системы контроля версий), те же шаблоны проектирования, то же ФП…

                              0
                              > Раз в год осваивать новый язык, — очень хорошо, но можно и раз в полгода, не повредит.

                              В одной чудесной книге — «Программист-прагматик» именно так и написано. Еще написано, что нужно одну книгу (техническую) хотябы раз в три месяца чиать. Тогда портфель знаний будет на уровне :)

                              А заточка на С++ — это просто когда тебе читают курс ООП и фиктивный (управляемый) указательна С++/СLI называют «крышечкой» без объяснения что это и зачем. Был у нас грешок на кафедре. Преподаватель ООП, до сих пор обидно, что такой отличный курс, так погано было преподнесен.
                                +1
                                С ООП не только у вас плохо, у нас тоже было, стыдно сказать, изучение Delphi / Builder'a со словами «а вот это — класс». Хотя это далеко не ООП, — это самые-самые начала ООП. В общем, этого курса тоже, можно сказать, не было.

                                Для противовеса можно вспомнить, что было хорошего. Математика была, много. Некоторую часть вел замечательный преподаватель с многолетним стажем. Лекции его всегда на высоте.

                                Сейчас я преподаю не на своей кафедре (ИВТ), но на родственной к ней (ПИМ). Если все сложится хорошо, на следующий год попробую забрать себе функциональное программирование у своего бывшего преподавателя. К сожалению, все его предметы были «спустя рукава», — потому что он хоть и профессор, а выпить горазд. В итоге его держат ради его звания, — есть негласные показатели, когда на кафедрах должно быть столько-то кандидатов, столько-то докторов. И с каждым годом эти цифры выдерживать труднее, потому что аспирантов очень мало, докторантов еще меньше. В этой статье написано правильно: чувствуется разрыв поколений.
                      –1
                      Вы высшее образование получаете, вас никто ничему не обязан учить.
                      Тогда следует переименовать его в «высшее самообразование», чтобы не смущать людей. И, конечно, ни дай бог вам когда-нибудь воспользоваться услугами проктолога-самоучки.
                    +1
                    Пару мелких замечаний по коду.

                    1. класс AbstractVector и интерфейс Vector: во-первых, из объявления интерфейса неясно, какую фабрику векторов будут использовать методы без аргумента `factory`. Нужно выбрать либо вариант, когда фабрика передаётся в конструторе, либо в каждом методе. На мой взгляд, первый вариант лучше. во-вторых, почему одни методы могут выкидывать эксепшен, а другие нет — хотя имя у них одно (это касается интерфейса)?

                    2. интерфейс IOConstants: очень плохая практика использовать интерфейс в качестве хранения констант, а потом его имплементить. Основное предназначение интерфейса — описание методов объекта. Константы — это уже конкретика реализации и для них есть простые классы либо перечисления (enum). Тем более IOConstants не объявляет ни одного метода.

                    3. имплементации интерфейсов и относящиеся к ним классы лучше выносить в отдельный под-пекедж `impl`, если вы хотите отделить абстракцию от конкретики (и так удобней будет иметь один api и несколько реализайций)

                    4. Поля, которые не предполагается менять, лучше делать `final`. Например в LinearSystem поля a, b не переопределяются (пусть даже сами поля изменяемы (mutable), но ссылки на них постоянны) — их можно сделать final.

                      0
                      Спасибо за замечания!

                      1) Я думал над тем, чтобы передовать фабрику в конструкторе, но на мой взляд это лишняя операция. По умолчанию просто создается ассоциированная с типом вектора фабрика. Это была большая проблема: понять какой именно вектор нужно создавать например при сложении двух: плотный + разреженый = плотный, а плотный * разреженый = разреженый. Я решил использовать фабрики и сделать так чтобы пользователь мог просто умножать вектора не думая о том какой будет результат, для этого и нужна фабрика, которая инстанциируется по-умолчанию. Если пользователь знает что ему нужно — передает фабрику.

                      2) Идея взята из download.oracle.com/javase/1.4.2/docs/api/java/io/ObjectStreamConstants.html Я знаю что практика плохая, Effective Java читал. Просто хотел сделать что-то очень похожее на классы из java.io.

                      3) Хорошее замечание, но я не хотел сильно перегружать API. Все должно было быть просто. Хотя я тут согласен, практика хорошая.

                      4) Согласен.
                      0
                      Решил сообщить для неравнодушных. Версия la4j-0.3.0 доступна для загрузки.

                      Новый официальный сайт: la4j.org
                      Relase notes: la4j.blogspot.com/2012/12/la4j-030-is-out.html
                      la4j @ GitHub: github.com/vkostyukov/la4j

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое