<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nikolay Grebenshikov</title>
    <description>The latest articles on DEV Community by Nikolay Grebenshikov (@ngrebenshikov).</description>
    <link>https://dev.to/ngrebenshikov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F280066%2F3e82da57-630a-4207-9200-25cde64ce232.jpg</url>
      <title>DEV Community: Nikolay Grebenshikov</title>
      <link>https://dev.to/ngrebenshikov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ngrebenshikov"/>
    <language>en</language>
    <item>
      <title>Migrating from Swift 2 to 5 in 2020</title>
      <dc:creator>Nikolay Grebenshikov</dc:creator>
      <pubDate>Thu, 03 Sep 2020 06:47:26 +0000</pubDate>
      <link>https://dev.to/ngrebenshikov/migrating-from-swift-2-to-5-in-2020-4io0</link>
      <guid>https://dev.to/ngrebenshikov/migrating-from-swift-2-to-5-in-2020-4io0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Task:&lt;/strong&gt; Build and publish an iOS app that built in 2016 using Swift 2 and kicked out from App Store.&lt;/p&gt;

&lt;p&gt;Now is 2020. Since 2016 Apple introduced many new requirements. It needs to build an application with the latest Xcode but the last Xcode can not work with Swift version less than 4. However it has a feature to convert Swift code automatically to a newer version. But you can not to convert 2nd version to 5th. You have to convert 2 to 3, 3 to 4 and 4 to 5. Moreover it needs different versions of Xcode for each step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common migration steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install Xcode&lt;/li&gt;
&lt;li&gt;Convert code automatically by Xcode&lt;/li&gt;
&lt;li&gt;Update libraries&lt;/li&gt;
&lt;li&gt;Make it working by manual changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  2 to 3
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://swift.org/migration-guide-swift3/"&gt;The official Swift 3 migration guide &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So an old Xcode version's needed to open, compile and convert Swift 2 code. The valid (newest) Xcode version for Swift 2 is &lt;a href="https://download.developer.apple.com/Developer_Tools/Xcode_8.3.3/Xcode_8.3.3.xip"&gt;Xcode 8.3.3&lt;/a&gt;. Unfortunately Xcode 8.3.3 doesn't work on the latest OSX Catalina. It needs at least High Sierra or earlier. This struggle was solved using &lt;a href="https://www.virtualbox.org"&gt;VirtualBox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When the correct OSX and Xcode were installed the code was converted automatically. The libraries were remaining. &lt;/p&gt;

&lt;p&gt;Firstly, it's good to have the version of the cocoa-pod CLI that fits that time. It's 1.3.1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;cocoapods &lt;span class="nt"&gt;-v&lt;/span&gt; 1.3.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key for a successful library update is to determine what version is suitable. It's easy if such information is on Pod page. E.g. for &lt;a href="https://cocoapods.org/pods/RappleProgressHUD"&gt;RappleProgressHUD&lt;/a&gt; there is information about versions for Swift 4 and newer. Another way is to choose by time in &lt;a href="https://github.com/CocoaPods/Specs/tree/master/Specs/4/5/5/RappleProgressHUD"&gt;Podspec&lt;/a&gt;. Late 2017 fits Swift 3.&lt;/p&gt;

&lt;h1&gt;
  
  
  3 to 4
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://swift.org/migration-guide-swift4/"&gt;The official Swift 4 migration guide &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is to convert Swift 3 to 4. It can be done using &lt;a href="https://download.developer.apple.com/Developer_Tools/Xcode_10.1/Xcode_10.1.xip"&gt;Xcode 10.1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The libraries were migrated the same way as above.&lt;/p&gt;

&lt;p&gt;There were several manual changes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Substring&lt;/strong&gt;&lt;br&gt;
They introduced a new way to handle the ranges.&lt;/p&gt;

&lt;p&gt;Swift 3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swift 4&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
      &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;offsetBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;offsetBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicit casting&lt;/strong&gt;&lt;br&gt;
Variables of type "Any" should be explicitly casted.&lt;/p&gt;

&lt;p&gt;Swift 3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="nv"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSArray&lt;/span&gt;
&lt;span class="o"&gt;..&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as?&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swift 4&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as!&lt;/span&gt; &lt;span class="kt"&gt;NSDictionary&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as?&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  4 to 5
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://swift.org/migration-guide-swift5/"&gt;The official Swift 5 migration guide &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, converting from Swift 4 to 5 is the easiest one and can be done on the latest Xcode 11. All code were converted automatically. Libraries were updated as above. Icons and launch screens were added for new sizes. &lt;/p&gt;

&lt;p&gt;Built. Published. Profit. ;)&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jessedo81?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jesse orrico&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/hard-work?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>pain</category>
    </item>
    <item>
      <title>A little trip through dependencies and accompanying difficulties</title>
      <dc:creator>Nikolay Grebenshikov</dc:creator>
      <pubDate>Fri, 17 Apr 2020 10:10:05 +0000</pubDate>
      <link>https://dev.to/ngrebenshikov/a-little-trip-through-dependencies-and-accompanying-difficulties-434o</link>
      <guid>https://dev.to/ngrebenshikov/a-little-trip-through-dependencies-and-accompanying-difficulties-434o</guid>
      <description>&lt;p&gt;It’s story where a little task causes an interesting trip through several open source libraries and programming languages. I’d like to mention that the text below is not the nagging about others’ or my code quality but just a yarn about how things are highly connected and how challenging and fun unraveling these links and finally solving a problem.&lt;/p&gt;

&lt;p&gt;I’ve got an iOS app - &lt;a href="https://apps.apple.com/by/app/moulinella/id1406645161"&gt;Moulinella&lt;/a&gt;. It’s a cross-platform app written on &lt;a href="https://haxe.org"&gt;Haxe&lt;/a&gt; using &lt;a href="https://openfl.org"&gt;OpenFL&lt;/a&gt; and &lt;a href="https://github.com/jiveui/jive"&gt;JiveUI&lt;/a&gt; frameworks and run on iOS, Android and &lt;a href="https://www.moulinella.com"&gt;in the web&lt;/a&gt;. I needed to support a document opening feature. So other apps could send specific files to my app.&lt;/p&gt;

&lt;p&gt;First of all I’d found &lt;a href="https://www.raywenderlich.com/813044-uiactivityviewcontroller-tutorial-sharing-data"&gt;a great tutorial about document sharing on iOS&lt;/a&gt;. There was some changes to XCode project but using OpenFL’s templates I did in the past. It was OK. The main code changes were related to &lt;a href="https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application?language=objc"&gt;UIApplicationDelegate&lt;/a&gt;. This part was several layers deeper than my app’s code. I hoped that OpenFL team passed this feature closer to me. It was a bit hard to find but they did it. &lt;a href="https://community.openfl.org/t/ios-appdelegate-application-openurl-options-not-being-called/9196/3"&gt;Singmajesty mentioned on the forum&lt;/a&gt; that there is lime.ui.Window.onDropFile event already, thanks to &lt;a href="http://www.libsdl.org"&gt;SDL library&lt;/a&gt;. This event provides an URL of a file that is passed to an app on iOS. Great! Here we can see two more layers: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/haxelime/lime"&gt;Lime&lt;/a&gt; - a foundational Haxe framework for cross-platform development. It provides the wrapper code for different platforms so it’s written on Haxe, C++, Objective-C and Java.  It’s a base for OpenFL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.libsdl.org"&gt;SDL&lt;/a&gt; - Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D. It’s base for Lime and written mostly on C;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Try #1:&lt;/strong&gt; Code was written, compiled, run but didn’t work well! Nothing happened.&lt;/p&gt;

&lt;p&gt;Oh, I forgot that I’d replaced SDL’s UIApplicationDelegate by mine already. It was needed to implement third party authentication: Facebook and VK. So &lt;a href="https://github.com/native-toolkit/sdl/blob/370d05558c31570e34c642303705a66a9d0d1547/src/video/uikit/SDL_uikitappdelegate.m#L493-L521"&gt;the code related to the onDropFile event&lt;/a&gt; just wasn’t run. OK, let’s &lt;a href="https://github.com/ngrebenshikov/extension-vk/blob/35fddff529fa919f7d21f8118f5b26f5eaa14a26/sample-include/project/SDLUIKitDelegate.mm#L30"&gt;call SDL’s code from mine&lt;/a&gt;. So I’d just added a small piece of Objective-C code. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try #2:&lt;/strong&gt; Code was written, compiled. I’d got an error from the linker - my code couldn’t find symbols for SDL’s code.&lt;/p&gt;

&lt;p&gt;Maybe the Lime library compiled badly (I’ve got the latest dev version of Lime) and doesn’t have corresponding symbols. Let’s compile Lime. Hm! Lime can not be compiled! I definitely did something wrong. After investigation the wrong part was an updating &lt;a href="https://github.com/HaxeFoundation/hxcpp"&gt;hxcpp library&lt;/a&gt; to the latest version. It emerged that the Lime dependents on some part of Hxcpp &lt;a href="https://github.com/HaxeFoundation/hxcpp/commit/e431d92809a521444594010cbe0dce4b836f6f18"&gt;that was deleted as unused&lt;/a&gt;. I had a hack and reverted that changes for me for now and &lt;a href="https://github.com/haxelime/lime/issues/1393"&gt;informed the Lime team&lt;/a&gt; about an issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try #3:&lt;/strong&gt; Lime compiled. But I still got an error from the linker - my code couldn’t find symbols for SDL’s code.&lt;/p&gt;

&lt;p&gt;Here I have to say that I’m not experienced C++ developer so didn’t find the cause earlier. After a quarter of an hour or more of googling why C++ linked could find symbols I learned that if the symbols were written on C it needs to link them differently (using &lt;a href="https://stackoverflow.com/questions/1041866/what-is-the-effect-of-extern-c-in-c"&gt;extern "C" linkage-specification&lt;/a&gt;). So I’ve added &lt;a href="https://github.com/ngrebenshikov/extension-vk/blob/35fddff529fa919f7d21f8118f5b26f5eaa14a26/sample-include/project/SDLUIKitDelegate.mm#L6-L9"&gt;the wrapper to my code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try #4:&lt;/strong&gt; Code was written, compiled, run and worked great!&lt;/p&gt;

&lt;p&gt;I was extremely happy that the problem was finished successfully! &lt;/p&gt;

&lt;p&gt;Now I’m thinking how I should perceive described situation. Firstly, I was losing time not doing something valuable for my customers but just fixing my faults. Secondly, it was an opportunity to understand better how the app works on the different layers and increase the code quality. Finally, the software is a complex thing and it’s tough to deal with it. &lt;/p&gt;

&lt;p&gt;When I spent several hours and went through several layers of the framework code I had a moment of satisfaction thinking how big and complex the modern software is but we (developers) can handle all this information structure. At that moment I realized how much I love and proud of my profession because it can give this kind of emotions.&lt;/p&gt;

&lt;p&gt;I hope you feel the same. &lt;/p&gt;

</description>
      <category>haxe</category>
      <category>developer</category>
      <category>motivation</category>
      <category>programming</category>
    </item>
    <item>
      <title>10 years of evolution together with Haxe</title>
      <dc:creator>Nikolay Grebenshikov</dc:creator>
      <pubDate>Fri, 27 Dec 2019 08:10:48 +0000</pubDate>
      <link>https://dev.to/ngrebenshikov/10-years-of-evolution-together-with-haxe-15i9</link>
      <guid>https://dev.to/ngrebenshikov/10-years-of-evolution-together-with-haxe-15i9</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Here is the chronicle that I might produce during the last 10 years running my little pet project &lt;a href="https://moulinella.com/"&gt;Moulinella&lt;/a&gt; but it’s written now by the huge help of repository’s history. I sincerely tried to describe how the project (especially, its dependencies) has been evolving and why. How new features, issues and external changes influenced it.&lt;/p&gt;

&lt;p&gt;At the end of the article, you can find the current state (platforms, services, languages, libraries) and the list of items that were used but passed away. So you can scroll to the end, scan the list to decide if it worth to read the whole article or just to find the parts you really interested in.&lt;/p&gt;

&lt;h1&gt;
  
  
  Changelog
&lt;/h1&gt;

&lt;h3&gt;
  
  
  April 2010, Idea, research
&lt;/h3&gt;

&lt;p&gt;I had some free time and my wife used to have fun &lt;a href="https://en.wikipedia.org/wiki/Cross-stitch"&gt;cross-stitching&lt;/a&gt;. These two things pushed me to realize that it would be interesting having software that can create a pattern of a custom image or photo. I thought it would be just a fun project and an examination of my abilities to develop algorithm related software. It would also give me some experience in product design and customer relationships.&lt;/p&gt;

&lt;p&gt;The fun was started immediately. I’d just had a painful problem - how to name a new application. The solution comes from the Frech word &lt;em&gt;mouliné&lt;/em&gt; that means a type of floss used for cross-stitch and &lt;em&gt;Maranello&lt;/em&gt; - a town in Nothern Italy known worldwide especially as the Ferrari home. "O" letter at the end was changed to “a” to make the title to be heard more like a female name. So Moulinella appeared!&lt;/p&gt;

&lt;h3&gt;
  
  
  May 2010, Discussions, Platform, UI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Flash, AsWing, HaxeNeuQuant&lt;/p&gt;

&lt;p&gt;Playing basketball with my friend (UI designer and partner) we talked about my idea of Moulinella. He found that it could be also a beneficial experience for him to create UI for an application. We chose to develop a web site. It seemed an internet application could find more users than a desktop application. &lt;/p&gt;

&lt;p&gt;I had a lot of experience in creating web applications. Several years I used Haxe/Flash Player and C#/Silverlight to create frontend parts of RIAs (&lt;a href="https://en.wikipedia.org/wiki/Rich_web_application"&gt;Rich Internet Application&lt;/a&gt;, a popular term that days). Flash Player was more spread than Silverlight so Flash became our platform. I also took &lt;a href="https://github.com/iiley/AsWing"&gt;AsWing&lt;/a&gt; UI lib for Flash since I was the most familiar with it. AsWing was written on ActionScript. So it was added to the project as SWC and Haxe externs were created.&lt;/p&gt;

&lt;p&gt;The core Moulinella feature is converting a picture to a pattern. Technically saying transforming a bitmap to a bitmap with smaller size and smaller colors palette containing only colors that have corresponding threads. Reducing the size was implemented in Flash so it was reused. Reducing the color palette should have been implemented. The first task was to select an algorithm for &lt;a href="https://en.wikipedia.org/wiki/Color_quantization"&gt;color quantization&lt;/a&gt;. There were considered octrees, K-means and &lt;a href="https://pdfs.semanticscholar.org/8af5/f783125b9485f688fe47c356676d14f4a811.pdf"&gt;Kohonen neural networks&lt;/a&gt;. The neural networks won because it was nearly effective as others but faster. So its open-source implementation was ported from C to Haxe as &lt;a href="https://github.com/ngrebenshikov/HaxeNeuQuant"&gt;HaxeNeuQuant&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  May 2010, PDF, Build process
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; AlivePDF, FlashDevelop, swfmill, Haxe 2&lt;/p&gt;

&lt;p&gt;Obviously, our users didn’t want just quantized bitmaps. They want printed patterns that have usable information about points in the cross-stitch matrix including threads codes, colors, lengths. We needed to prepare our generated patterns for printing. PDF was selected as a format to layout pattern information and to give users the ability to print. Fortunately, the Flash ecosystem had &lt;a href="https://github.com/riadvice/AlivePDF"&gt;the AlivePDF library&lt;/a&gt; for these purposes.&lt;/p&gt;

&lt;p&gt;The development had been started. So here are some points about the development environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Haxe v2.05&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.flashdevelop.org"&gt;FlashDevelop&lt;/a&gt; became a Haxe IDE that fit my needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Almost the whole build process was covered by FlashDevelop. Only putting the external libraries to the resources usable from a Haxe application was covered by the &lt;a href="http://www.swfmill.org"&gt;swfmill&lt;/a&gt; (command-line tool that generates SWF files) in a batch file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The repository was Mercurial in Bitbucket Cloud because Bitbucket gave free private repositories.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  20 June 2010, Initial architecture
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Architecture&lt;/p&gt;

&lt;p&gt;I wanted to spend as less money as possible. So the good idea was to reduce the cost of the server infrastructure and do all heavy processing (the pattern preparation) on the client-side. The whole architecture was extremely simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Linux&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apache HTTP Server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Static HTML, CSS&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flash application&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  25 June 2010, Build libraries from sources, scripts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Flex, compc, AlivePDF, AsWing, Windows batch scripts&lt;/p&gt;

&lt;p&gt;I started building AlivePDF and AsWing from the source because wanted to have the latest versions. So Flex Compiler (compc) became a part of the environment. A couple of batch scripts were added to compile libraries and resources with them.&lt;/p&gt;

&lt;h3&gt;
  
  
  23 July 2010, Server appeared
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; PHP, Haxe Remoting, MySQL, ActiveRecord, record-macros&lt;/p&gt;

&lt;p&gt;It wasn’t proved that the app created cross-stitch patterns well enough for users. It needed some user’s feedback to discover the quality of the algorithm. Here more server code appeared. The server code was written on Haxe as well. &lt;a href="https://haxe.org/manual/std-remoting-connection.html"&gt;Haxe Remoting&lt;/a&gt; was used to communicate with the client. PHP was selected as the target platform since it’s easy to configure and it’s available everywhere. The database was also pretty understandable - MySQL. I used &lt;a href="https://en.wikipedia.org/wiki/Active_record_pattern"&gt;the ActiveRecord approach&lt;/a&gt; to communicate with DB that was a part of the Haxe standard library (&lt;a href="https://github.com/HaxeFoundation/record-macros"&gt;Since Haxe 4 it’s a separate library - record-macros&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  28 July 2010, Apache Ant
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; HXML, Ant, Java&lt;/p&gt;

&lt;p&gt;I used FlashDevelop and batch scripts to build client, server, and resources so far. It was becoming challenging to manage the build process and keep the accurate sequence manually. I had already used the Apache Ant build processor and it looked suitable for the case. So it was chosen.&lt;/p&gt;

&lt;p&gt;The compilation parameters moved from FlashDevelop project files to &lt;a href="https://haxe.org/manual/compiler-usage-hxml.html"&gt;HXML&lt;/a&gt; files. So the compiler executed by Ant script could use them to build modules. Libraries and resources building also moved to Ant. So I got a single command to run to build the whole system.&lt;/p&gt;

&lt;h3&gt;
  
  
  23 July 2010, Getting known about the user’s behavior
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; gaforflash&lt;/p&gt;

&lt;p&gt;Clearly, you can not make an application better without knowledge of how the users use it. So every important feature in the client was wrapped by Google Analytics call. Flash ecosystem had the &lt;a href="https://code.google.com/archive/p/gaforflash/"&gt;gaforflash&lt;/a&gt; library for this purpose.&lt;/p&gt;

&lt;h3&gt;
  
  
  7 July 2011, Moving to haXeAsWing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; AsWing, haXeAsWing&lt;/p&gt;

&lt;p&gt;Great news! AsWing was ported to Haxe by its owners. Let’s get rid of a bucket of ActionScript code and jump to the haXeAsWing library. Unfortunately, AlivePDF and gaforflash still practiced ActionScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  January 2012, Editor
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; ActiveRecord&lt;/p&gt;

&lt;p&gt;Implementing an editor for cross-stitch patterns didn’t add any new libraries and approaches. It grew the server and client sides. A lot of features were implemented on the server using the ActiveRecord approach: storing users, sessions, patterns. The client was extended by painting features.&lt;/p&gt;

&lt;h3&gt;
  
  
  August 2012, Localization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Ant, XML, XSLT&lt;/p&gt;

&lt;p&gt;Moulinella became multilingual. Actually two lingual - only English and Russian. All strings were put into separate XML files for different languages. These files were used to create a Haxe source file using XSLT every build using Ant. &lt;/p&gt;

&lt;h3&gt;
  
  
  December 2012, IDE on Mac
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; FlashDevelop, IntelliJ IDEA&lt;/p&gt;

&lt;p&gt;I was a FlashDevelop fan for several years but changed a platform from PC with Windows to Mac. Running FlashDevelop was really tricky via a virtual machine. I thought it was overcomplicated and found IntelliJ IDEA with the Haxe plugin. It worked for me at that time and works now.&lt;/p&gt;

&lt;h3&gt;
  
  
  2013, Internship
&lt;/h3&gt;

&lt;p&gt;That year I didn’t invest much time into Moulinella because of my other initiatives. But I’d got a student to grow for other projects. He was offered to attend an internship in Moulinella. He proved to be an extremely productive engineer. His job was an implementation of interconnection with the threads shop and running our application inside Russian social networks (VK, Odnoklassniki).&lt;/p&gt;

&lt;h3&gt;
  
  
  2014, Nothing
&lt;/h3&gt;

&lt;p&gt;Just maintaining and getting users ;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Winter 2015, New Haxe and getting rid of Flash
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Javascript, Flash, OpenFL, Haxe 3, AlivePDF, openfl-alivepdf, gaforflash, haxe-ga&lt;/p&gt;

&lt;h3&gt;
  
  
  The Flash’s death was felt like reality. It was time to go beyond and get rid of Flash and embrace Javascript as a WEB assembler. Luckily, OpenFL (an open-source initiative to create a cross-platform runtime with Flash API ) appeared at that time. It was wonderful to just add the library and get a web-application that just works.
&lt;/h3&gt;

&lt;p&gt;There were other ActionScript libraries in the project: AlivePDF and gaforflash. AlivePDF was ported to Haxe by me - &lt;a href="https://github.com/ngrebenshikov/openfl-alivepdf"&gt;openfl-alivepdf&lt;/a&gt;. gaforflash was replaced by another Google Analytics library written on Haxe - &lt;a href="https://github.com/SempaiGames/haxe-ga"&gt;haxe-ga&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Winter and Spring 2015, Jive UI birth
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; jive, MVVM, Data Binding, HML, BindX&lt;/p&gt;

&lt;p&gt;In 2015 HaxeAsWing seemed outdated since it adopted ideas from Java Swing officially released as a part of JDK in 1998. There happened new approaches as &lt;a href="http://en.wikipedia.org/wiki/Model_View_ViewModel"&gt;Model-View-ViewModel&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/UI_data_binding"&gt;Data Binding&lt;/a&gt;. I believed new ones were cool and could help develop faster and with a better attitude. So started adoption of them into HaxeAsWing. The result was named &lt;a href="https://github.com/jiveui/jive"&gt;Jive - a cross-platform UI framework for Haxe&lt;/a&gt;. Views were XML files similar to &lt;a href="https://en.wikipedia.org/wiki/MXML"&gt;MXML&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Extensible_Application_Markup_Language"&gt;XAML&lt;/a&gt;. &lt;a href="https://github.com/profelis/hml"&gt;HML&lt;/a&gt; library was used to generate Haxe code based on these XML views. &lt;a href="https://github.com/profelis/bindx2"&gt;BindX&lt;/a&gt; library brought the Data Binding between views and view models to life.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring 2015, SVG engine experiments
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; jive, openfl-snapsvg, Snap.SVG&lt;/p&gt;

&lt;p&gt;Flash and OpenFL were widely used for 2D games with bitmap assets. So OpenFL had the bitmap nature inside such as images, textures, the canvas. Moulinella and Jive had a vector-based core. It felt more natural to use the SVG engine of a browser to show Moulinella’s UI. OpenFL provided the ability to extend its backend to render core graphics. So did I implementing &lt;a href="https://github.com/ngrebenshikov/openfl-snapsvg"&gt;openfl-snapsvg&lt;/a&gt; - a backend that used Snap.SVG to manipulate SVG content of a page and display whole graphics provided by OpenFL: points, lines, paths, text fields, etc. &lt;a href="http://ngrebenshikov.github.io/openfl-snapsvg/"&gt;Demos are still available and working&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  May 2015, WWX 2015
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; speeches&lt;/p&gt;

&lt;p&gt;As a result of experiments and the commitment I’ve described above, I became a speaker on &lt;a href="https://www.silexlabs.org/wwx2015-schedule-and-speakers/"&gt;World Wide Haxe Conference 2015&lt;/a&gt;. The first time I talked publicly in English took place in Mozilla’s office in Paris. &lt;a href="https://haxe.org/videos/conferences/wwx-2015/jive-the-renovation-of-aswing-by-nickolay-grebenshikov.html"&gt;Here is the video of my speech "Jive: the renovation of AsWing"&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  July 2015, New ways to satisfy users, CLI
&lt;/h3&gt;

&lt;p&gt;*&lt;em&gt;Tags: *&lt;/em&gt;С++, hxcpp, hxargs, openfl&lt;/p&gt;

&lt;p&gt;Moulinella was only a creation tool so far. But a lot of content created using other applications could be found on the Internet. I believed that giving the ability to open and create PDF of patterns in different formats would bring more users than just a tool. So I started working on a converter from other formats to ours. Firstly this was a command lime OpenFL application that used the C++ target and compiled natively to the specific operating system. The &lt;a href="https://lib.haxe.org/p/hxargs"&gt;hxargs&lt;/a&gt; library was really helpful to deal with command-line arguments.&lt;/p&gt;

&lt;h3&gt;
  
  
  2016, Jive 2.0
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; speeches, innovation, failure, SVG, CLI, Neko&lt;/p&gt;

&lt;p&gt;I had participated in the development of several other applications using Jive. It caused the appearance of a group of developers that were using Jive (5 persons). Doing that projects we discovered Jive’s weak parts and decided to fix them. The pivoting brought us to the redeveloping it from scratch as a cross-platform UI framework for mobiles. We presented our results on &lt;a href="https://www.silexlabs.org/wwx2016-is-coming/"&gt;World Wide Haxe Conference 2016 in Paris&lt;/a&gt;. My colleague Maxim Bekhterev was a speaker at that time with me as an underground wizard. &lt;a href="https://haxe.org/videos/conferences/wwx-2016/jive-ui-for-mobile-platforms-by-maxim-bekhtere.html"&gt;Here is the video of Maxim’s talk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Later in 2016, we stopped working on the next version of Jive. The causes were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;the applications based on Jive were not as good as developed on official platform languages and frameworks. The main points were the lack of performance and high power consumption;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;there were no new Jive related projects;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;it was quite tough to develop and maintain so large library as a UI library. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Moulinella still existed and I decided to adopt some new features invented for Jive 2.0. E.g., the SVG component and the CLI. CLI provided the ability to put HML views anywhere in the project. It was also written on Haxe and used Neko as a target as other haxe libraries CLIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2016, Crawling, Searching, Internship
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Job queue, Concurrency, hxcpp, Sphinx, MySQL&lt;/p&gt;

&lt;p&gt;Moulinella project provided the ability to learn for two more developers this year. Their work elaborated on the idea to make Moulinella a more content-oriented product. We tried to crawl the Internet to find cross-stitch patterns and provide them to our users. It would be cool if they could search and open cross-stitch patterns from the Internet in the Moulinella application.&lt;/p&gt;

&lt;p&gt;The interns developed a crawler, a supervisor with a job queue based on MySQL. Both the crawler and supervisor used the C++ target. There were some issues with the concurrency solved by job ID sharding to separate workers. Another part was searching. &lt;a href="http://sphinxsearch.com"&gt;Sphinx&lt;/a&gt; helped us to index the cross-stitch patterns metadata. It allowed us to implement a full-text search through patterns. &lt;/p&gt;

&lt;h3&gt;
  
  
  Summer 2016, IPv6 on iOS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; openfl-ios-networking, extensionkit&lt;/p&gt;

&lt;p&gt;Starting in June 2016, Apple required iOS apps to support IPv6. At that time the issue was not about Moulinella but the code that was developed for other projects would be reused in Moulinella later.&lt;/p&gt;

&lt;p&gt;The problem was that hxcpp didn’t support IPv6 completely. There was no space to wait so I developed an OpenFL extension (&lt;a href="https://github.com/jiveui/openfl-ios-networking"&gt;openfl-ios-networking&lt;/a&gt;) that extends haxe.Http class using calls to the native iOS HTTP framework. That was enough to cover our needs for client-server communication.&lt;/p&gt;

&lt;p&gt;This extension was based on &lt;a href="https://github.com/bazzisoft-openfl-extensions/extensionkit"&gt;the OpenFL extension kit&lt;/a&gt; which gave the common functionality such as callbacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring 2017, Crawling-searching environment
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; vagrant&lt;/p&gt;

&lt;p&gt;Having several crawlers, a supervisor and indexer made the development and deployment more complex. We started using &lt;a href="https://www.vagrantup.com"&gt;vagrant&lt;/a&gt; to configure and test the crawling-searching environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fall 2017, Rectitude
&lt;/h3&gt;

&lt;p&gt;Doing our experiment with crawling we discovered that the most cross-stitch patterns on the Internet are copied and published illegally. I believed and believe it would be not fair to help to spread these cross-stitch patterns over the Internet. So the crawling-searching work was stopped. &lt;/p&gt;

&lt;h3&gt;
  
  
  Summer 2018, Mobile applications
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; hxcpp, openfl, Xcode, iOS, Android.&lt;/p&gt;

&lt;p&gt;What if not to print PDF cross-stitch patterns on paper but put them into smartphones or tablets that are always with people. What a great idea I realized that year. Moreover, OpenFL applications could be compiled for iOS and Android without any difficulties using the hxcpp library. Especially because of Jive that was platform-agnostic UI library dependent only on OpenFl API. So the next goal became to make Moulinella mobile apps.&lt;/p&gt;

&lt;p&gt;The main challenges were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;to support touches instead of a mouse;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;different PPI;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;smaller screens than desktops have.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So all these problems were solved and packed into Jive’s mobile theme.&lt;/p&gt;

&lt;p&gt;At that time the build process and especially deploy process included Xcode as a tool to debug and to publish iOS applications. The android application build process covered just by OpenFL tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  September 2018, Pivoting to an interactive patterns shop and service
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; profit&lt;/p&gt;

&lt;p&gt;Moulinella had been a non-profit web service for 8 years and I became getting less fun from it as earlier. Keeping it the same didn’t work for me. I needed some changes to begin earning money. I believed that there is a thing better than great service and it’s great content. So I started to find a way to provide great content (beautiful cross-stitch patterns) and great service to our users and ask them to pay for it. I found a new partner, a pattern designer/seller, who already had a pool of patterns to sell.&lt;/p&gt;

&lt;p&gt;Thinking together we determined new features to develop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a shop;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;private sections on web site for users and designers;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a new service to mark the progress of stitching. It would go to our apps on all platforms and make the patterns interactive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  October 2018, Dashboard for designers and users
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Javascript, ReactJS, haxe-react, Redux, haxe-redux, React Router, haxe-react-router, UIKit, npm, browserify, uglifyjs.&lt;/p&gt;

&lt;p&gt;Since we were going to sell patterns it needed to upload them, convert to our format, prepare the metadata, handle versioning and move to the shop. These type of features causes appearing a new piece of software - a designer dashboard. It seemed the one with tricky logic but didn’t need to be cross-platform since they prepared their patterns on the desktop computers and it’s easy to open a browser and upload pattern using a web application. So the decision was to build a designer’s dashboard just as a web application.&lt;/p&gt;

&lt;p&gt;Having Haxe as a base language gave me the ability to reuse the codebase and to communicate easily with the services that already developed. Since the target is only Javascript I considered adopting the libraries from the whole Javascript ecosystem. My needs were a UI framework that gives an application structure, a UI framework that can hide HTML/CSS and gives common UI components. I considered React, Angular, Vue for the first need and Bootstrap and UIKit for the second. I’d chosen ReactJS and its Haxe extern &lt;a href="https://github.com/massiveinteractive/haxe-react"&gt;haxe-react&lt;/a&gt; because it seemed more mature (provided by the huge player - Massive Interactive) than other externs for the JS frameworks. I’d also selected &lt;a href="https://getuikit.com"&gt;UIKit&lt;/a&gt; just because it looked more beautiful visually for me. The UIKit needed to develop externs but &lt;a href="https://haxe.org/manual/target-javascript-external-libraries.html"&gt;it was easy to do&lt;/a&gt;. This approach was also checked during a student project I managed - &lt;a href="https://github.com/abakan-student-projects/scholae-web"&gt;Scholae&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ReactJS brought Redux, React Router and their externs &lt;a href="https://github.com/elsassph/haxe-redux"&gt;haxe-redux&lt;/a&gt; and &lt;a href="https://github.com/elsassph/haxe-react-router"&gt;haxe-react-router&lt;/a&gt;. It was needed to add more structure to the application and make it easier to maintain.&lt;/p&gt;

&lt;p&gt;The build process of such a mixed application worked a bit different. It involved &lt;a href="https://www.npmjs.com"&gt;npm&lt;/a&gt; to get modules then haxe to compile and then &lt;a href="http://browserify.org"&gt;browserify&lt;/a&gt; and &lt;a href="https://github.com/markknol/hx-uglifyjs"&gt;uglifyjs&lt;/a&gt; to prepare a resulted JS to run in the browser. All these steps were put into my ant script so we still have one script to build the whole system.&lt;/p&gt;

&lt;h3&gt;
  
  
  November 2018, Promises
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Haxe Remoting, HaxeTink&lt;/p&gt;

&lt;p&gt;I’d already wrapped Haxe Remoting with callbacks to create service clients. They said there was an approach that gives a better definition of the control flow of asynchronous logic, reduced coupling, better error handling, and improved readability - promises. So adopted them using &lt;a href="https://haxetink.github.io"&gt;Tinkerbell for Haxe&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring 2019, Internship, Reusing Scholae’s experience
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; student project&lt;/p&gt;

&lt;p&gt;A lot of haxe-react related work was done for &lt;a href="https://github.com/abakan-student-projects/scholae-web"&gt;our student open-source project&lt;/a&gt; and then adopted for Moulinella by two smart interns. They moved their solutions for UI layout, authentification, and notifications.&lt;/p&gt;

&lt;h3&gt;
  
  
  March 2019, Sending emails
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; smtpmailer, asys&lt;/p&gt;

&lt;p&gt;Owning a mail server was a pain. It’s hard to be sure that it was not in the blacklist and our messages accepted by recipients’ servers. So we moved to a third-party email service it gives us confidence about messaging and brought a couple of libraries: &lt;a href="https://github.com/benmerckx/smtpmailer"&gt;smtpmailer&lt;/a&gt; and &lt;a href="https://github.com/benmerckx/asys"&gt;asys&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  April 2019, Running long jobs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Apache HTTP server, hxcpp, Docker, Job Queue, RabbitMQ, AMQP, Cron&lt;/p&gt;

&lt;p&gt;When a designer uploads a pattern or changes its metadata it needs to be checked, transformed to our format,  thumbnails and previews should be prepared, PDF should be generated and maybe emails should be sent. And all of it for different languages. Certainly, it would take some time and it shouldn’t be doing during an uploading HTTP request.&lt;/p&gt;

&lt;p&gt;So I moved long job-related features to a separated module - worker. It can be run outside the Apache HTTP server as an independent service and receive signals from other parts of the system through RabbitMQ. It was brought to life with the help of &lt;a href="https://github.com/geekrelief/hxamqp"&gt;the hxamqp library&lt;/a&gt; and &lt;a href="https://github.com/ngrebenshikov/hxamqp"&gt;my commitment to support Haxe 3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Having workers compiled natively for a specific operating system would give a performance reward. It’s a great feature of the Haxe code and hxcpp to be compiled to the C++ target and then to a platform. There might be an obstacle if the build system is different from the target one. My build system was Mac but the target was a Linux server. Docker came for help here. It took some effort to configure the docker environment and put it into the Ant script. But it gave the ability to create Linux executables on Mac.&lt;/p&gt;

&lt;p&gt;The job initiators were our web site users so far. But the features like subscriptions needed the system itself to be a job emitter. Here the Cron Linux service came to run several jobs regularly.&lt;/p&gt;

&lt;h3&gt;
  
  
  April 2019, Mobile applications deployment
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; fastlane, compiletime&lt;/p&gt;

&lt;p&gt;Xcode and Google Play Console site were used to deploy mobile builds for testing and publishing. It was a certainly time-consuming manual operation. Being in 2018 on Haxe US Summit in Seattle I heard &lt;a href="https://haxe.org/videos/conferences/haxe-summit-us-2018/creating-mobile-development-pipeline-adam-breece.html"&gt;a talk from a FlowPlay developer about how they adopted Fastlane for their Haxe projects&lt;/a&gt;. So did I and became completely happy doing it in one click.&lt;/p&gt;

&lt;p&gt;After deployment the good thing to give users (especially testers) the ability to identify what the version of the app exactly is. The &lt;a href="https://github.com/jasononeil/compiletime"&gt;compiletime&lt;/a&gt; library gives you the ability to put dates, versions to the code during the compilation.&lt;/p&gt;

&lt;h3&gt;
  
  
  May 2019, Getting money from mobile users
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; extension-iap, extension-admob, Objective-C, Java&lt;/p&gt;

&lt;p&gt;Moulinella was a free mobile app for years. Now we were planning to make some money adding a premium subscription and showing commercials. Corresponding libraries were found &lt;a href="https://github.com/HaxeExtension/extension-iap"&gt;extension-iap&lt;/a&gt; and &lt;a href="https://github.com/HaxeExtension/extension-admob"&gt;extension-admob&lt;/a&gt;. They needed some fixing so it was done by forking them: &lt;a href="https://github.com/ngrebenshikov/extension-iap"&gt;iap&lt;/a&gt;, &lt;a href="https://github.com/ngrebenshikov/extension-admob"&gt;admob&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  June 2019, Pattern viewer performance tuning
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Display List, Bitmap, Tilemap, Graphics.drawPath, 100K tiles&lt;/p&gt;

&lt;p&gt;The main feature of the mobile apps was a cross-stitch pattern viewer. It needed to display a matrix of square areas covered by a layer of lines and curves. This feature should be very dynamic. We must have the ability to navigate, scale, disable layers, make the squares or lines partly transparent. &lt;/p&gt;

&lt;p&gt;In the beginning, it was implemented by creating two bitmaps by drawing on them square objects and lines on the fly and putting the bitmaps into the OpenFL display list one on another. Even the first testing discovered performance issues.&lt;/p&gt;

&lt;p&gt;After several experiments, we found a combination that was enough for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Not create an almost full-screen size bitmap but create a smaller one with distinct parts of the pattern’s matrix and use it as a Tilemap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filter squares and lines that shouldn’t be rendered in case of scaling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cut lines to fit the screen in case of scaling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use batching to draw lines (Graphics.drawPath).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These changes gave the ability to show the patterns with about 100K stitches. We even met the Tilemap limit of 2^14 of tiles. Having several Tilemaps helped. It didn’t give 60 fps but it worked well enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  August 2019, Getting money from Web users
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Dynamic Web pages,** **Paypal, Yandex.Checkout, Tax online services, Haxe Web dispatcher, Haxe Templates, PHP&lt;/p&gt;

&lt;p&gt;The current architecture didn’t include the HTML generation on the server. We just had static pages, web services, and huge JS clients. When the shop occurred in our plans we started thinking about SEO and giving the users and search crawlers identic and relevant content. So our servers started generating the shop HTML pages by a new PHP application configured via &lt;a href="https://httpd.apache.org/docs/current/mod/mod_rewrite.html"&gt;mod_rewrite&lt;/a&gt; to process relevant HTTP requests. I adopted &lt;a href="http://old.haxe.org/manual/dispatch"&gt;a simple web dispatcher component&lt;/a&gt; for routing and &lt;a href="https://haxe.org/manual/std-template.html"&gt;Haxe templates&lt;/a&gt; to have already prepared HTML parts.&lt;/p&gt;

&lt;p&gt;Since we were planning to sell subscriptions and patterns it needed to have some ways to charge users. We selected Paypal for worldwide users and Yandex.Checkout for Russians. Russian laws also said to have an online integration with the state tax service to give them the ability to check your cash flow.&lt;/p&gt;

&lt;p&gt;I’m not sharing much here or opensource the code but it needs to be mentioned because of effort to make this integration happen. And yes it’s possible using Haxe externs to adopt Paypal and other services SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  September 2019, Client code capsule
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; capsule&lt;/p&gt;

&lt;p&gt;The client code related to authentification, accessing services was in the big JS application - the user/designer dashboard. But the same features were needed for the shop pages to do small things with our services (like getting some information from the server, filling a cart, etc). Taking the large JS file to the shop pages looked weird so I created a separate JS module from the same code base taking only specific classes and functions. That module has a name - Capsule.&lt;/p&gt;

&lt;h3&gt;
  
  
  October 2019, Third-party authorization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; extension-facebook, extension-vk, extension-appleid, Objective-C, Java&lt;/p&gt;

&lt;p&gt;Users mentioned that they wanted to log in through their social network accounts. We found the most popular variants were Facebook for international users and VK for Russians. &lt;/p&gt;

&lt;p&gt;So I started integrating them into the application. The web part was the easiest one. Each of these social networks had JS SDKs that could be simply used with externs to put them into Haxe codebase.&lt;/p&gt;

&lt;p&gt;The integration of them into mobile applications was a bit tricky. Especially because there was only &lt;a href="https://github.com/HaxeExtension/extension-facebook"&gt;an OpenFL extension for Facebook&lt;/a&gt;. Even this extension needed some rework. So &lt;a href="https://github.com/ngrebenshikov/extension-facebook"&gt;my fork&lt;/a&gt; of another fork appeared. &lt;a href="https://github.com/ngrebenshikov/extension-vk"&gt;VK extension&lt;/a&gt; was created based on the Facebook one. I was so happy when Apple brought me to support their Apple Sign In because of its obligation. Here is &lt;a href="https://github.com/ngrebenshikov/extension_appleid"&gt;the extension-appleid&lt;/a&gt; I developed.&lt;/p&gt;

&lt;h3&gt;
  
  
  November 2019, Crashes, GC, Driver to update Haxe version to 4
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; C++, hxcpp, Neko, Haxe 4, hx3compat&lt;/p&gt;

&lt;p&gt;On some big patterns, we’d got crashes accessing wrong memory addresses. It seemed that GC worked wrong. I worked it out for one pattern by tuning hxcpp GC by its parameters to do more checks. But tester found patterns where it didn’t work. I was completely confused. This issue affected the C++ target: mobile applications and workers. Thanks to Haxe multi-targeting the worker moved to the Neko target and the issue disappeared. But it didn’t work for mobile apps because C++ was the only case for it. At least I thought so. &lt;em&gt;Correct me, please, if I’m wrong in comments.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lately found that the other developers experienced similar issues with GC that time but with Haxe 4. I was still on Haxe 3. After some time the solution was found by hxcpp maintainers and committed into the latest version that was for Haxe 4 of course. That was a super driver to upgrade the Haxe version.&lt;/p&gt;

&lt;p&gt;I could say that this update went smoothly especially because of the &lt;a href="https://github.com/HaxeFoundation/hx3compat"&gt;hx3compat&lt;/a&gt; library. There were a few changes in my code and libraries. Even the issue in the Haxe standard library was found. But I must say very thank you to the Haxe team for their effort to fix issues and deliver the next Haxe version.&lt;/p&gt;

&lt;h4&gt;
  
  
  December 2019, Notches
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; extension-safearea&lt;/p&gt;

&lt;p&gt;Some recent smartphones have a notch. Android skips a notch by default. That’s OK but iOS doesn’t. As we don’t support it our UI looked ugly on iOS. Obviously, we should use safe areas for these devices. Luckily the library had already implemented - &lt;a href="https://github.com/HaxeExtension/extension-safearea"&gt;extension-safearea&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  January 2020, Conclusion
&lt;/h3&gt;

&lt;p&gt;The last development cycle has been finished. So it needs to look behind and do some retrospective and go further and think about new opportunities. This article is a part of it. Thank you for your comments!&lt;/p&gt;

&lt;h1&gt;
  
  
  Current state
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;create cross-stitch patterns by photo;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;save patterns on the server;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sell patterns;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;show patterns and save progress on them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Platforms/Haxe targets&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Linux server: PHP, C++, Neko&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Web browser: Javascript&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;iOS: C++&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Android: C++&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Third-party applications/services&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTTP server: Apache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PHP Apache module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DBMS: MariaDB/MySQL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queue: RabbitMQ&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cron service&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Developed applications/services&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Worker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CLI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Viewer / Wizard / Editor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Web services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic HTML pages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User /  Designer / Admin private sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Static files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Converter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Capsule&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Languages/Tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Haxe 4&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Objective-C&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Java&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C++&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;XML&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;XSLT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Javascript&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SVG&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Xcode&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IntelliJ Idea&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Approaches / Other tags&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Client/Server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ActiveRecord&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MVVM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data Binding&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concurrency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Job queue&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AMQP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Display List&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tilemap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paypal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Yandex.Checkout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tax online services&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Libraries&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Haxe Remoting&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Haxe Web Dispatcher&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Haxe Templates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hx3compat&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openfl&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;lime&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hxcpp&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hxargs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HaxeTink (Tinkerbell for Haxe)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;record-macros&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;jive&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;svg&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;actuate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bindx2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openfl-alivepdf&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;neuquant&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;jsFileDialog&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;swf&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;haxe-ga&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension-iap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension-admob&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension-facebook&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension-vk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension-appleid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension-safearea&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;compiletime&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;uglifyjs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extensionkit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openfl-ios-networking&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;haxe-react + ReactJS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;haxe-react-router + React Router&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;haxe-redux + Redux&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;html-entities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;asys&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;smtpmailer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mtwin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hxamqp&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Build / Deployment tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;java&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ant&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ant-jsch (SSH)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fastlane&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;node&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;npm&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;browserify&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hg&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Used but passed away&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;gaforflash&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;compc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;swfmill&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openfl-snapsvg&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Snap.SVG&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sphinx&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;vagrant&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FlashDevelop&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Speeches&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"Jive: the renovation of AsWing" on World Wide Haxe Conference, 2015&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Jive: UI for mobile platforms" on World Wide Haxe Conference, 2016&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Hire me
&lt;/h1&gt;

&lt;p&gt;Thank you for reading till the end! Hire me if you’re looking for an engineering manager or an engineer with the experience above. &lt;a href="https://www.linkedin.com/in/nikolaygrebenshikov/"&gt;Full my profile is accessible on LinkedIn&lt;/a&gt;. You can contact me via &lt;a href="mailto:grebenshikov.n@gmail.com"&gt;grebenshikov.n@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>haxe</category>
      <category>indie</category>
      <category>moulinella</category>
      <category>history</category>
    </item>
  </channel>
</rss>
