Manual subscription management
Semi-automatic management with takeUntil
Using the async pipe
In the last couple of months I started to shift my attention from coding to making sure the team works properly. This of course brings lots of challenges and frustrations – but also you learn a lot about yourself.
One area it hit me very hard is mentoring people. I always did it, even at my first gig I trained and coached people in C# stuff. But boy I did it horribly wrong.
I spent a big chunk of my free time in the last couple of months to build an iOS app. The app’s primary feature is to connect with people who are in your close (close as in Bluetooth) range. Here’s what I’ve learned in the process.
Running anything in the background in iOS is painful. From Apple’s point of view this is perfectly reasonable – they don’t want you to drain their devices’ precious battery. On the other hand the UX is terrible. You’ll only get one shot to convince your users to give you the desired permission. If they don’t do it then comes the “leave the app and change the settings” scenario. Instant churn.
The Location Services background permission is a special case. Apple will constantly ask the user in random intervals if they are aware that your app does location scans in the background. This can quickly lead your users to disable it as it was some kind of malware.
Then there are some badly worded system dialogs – my favorite is the “Turn on Bluetooth” dialog which has two buttons: OK and Settings. You’d assume that the OK button would turn on Bluetooth but it just closes the dialog. It’s really nice since users generally don’t read these at all, just bluntly hit OK and expect the problem to go away.
The background settings are brittle at best. There’s an app level permission, and there’s a permission for the whole system (parental lock excluded). It again makes sense from the user’s side, but from the app’s side it’s disastrous. The API calls will just return that there’s no required permission to run, but they won’t tell you why. It’s quite hard to guide the user through the problem if you don’t know the cause.
In a bad way. First there’s no way to tell if the device Bluetooth is turned off, or is not supported at all (aka iPhone 4). Now I lied, you can deduce this with checking various constants, but if you’d like to do this cleanly using the API you’re doomed.
Then there’s the plist fun when you need to add the keys to support background Bluetooth running. You can also have a lot of fun with events not firing, or firing with a huge (40 secs) of latency. In a real time app like mine, this is a huge deal.
The short answer is that it’s impossible. You will only be able to broadcast iBeacons when your app is in the foreground. The problem is that there are tons of resources (mostly stackoverflow users in despair) who claim otherwise or offer creative ways around the problem. But nothing works. What works is a UX which rewards the user for opening and engaging with the app. Forget everything else.
Ranging or geofencing (region entering and leaving)? What constitutes a region? What can I do in the background?
I was really confused at first. Region entering can run in the background, but with a limited set of regions (I remember 20 for the whole device). Ranging cannot run when you’re in the background. The problem is when you use iBeacons you’d like to identify them (major/minor anyone?). Region entering won’t do this for you, you’ll need ranging.
But a little creativity goes a long way. Entering a region will wake up your app and you’ll have 5 seconds to do what you need. Now you can use these 5 seconds for ranging, since you’re not in the background anymore. Problem solved.
If I were to start again this app I’d do it on Android. I finished it because the emotional investment was huge. On iOS you’d get seriously hindered functionality when you try to be creative with iBeacons. They seem to be a perfect fit for indoor navigation but when you try to do something different you’d hit into way too much barriers.
Oh, the app is waiting for review right now. I’m very interested to see if Apple approves it. I’ll post about it when it’s done.
Recently I tried to draw some binary image data to the canvas. The image data was in a Uint8Array but it was already compressed, so no raw RGB.
You see the canvas context has some convenience functions working with binary data, like putImageData. Normally you would use it like this:
Be warned though that putImageData only works with RGB values, not an already compressed image, like a JPEG or PNG file data.
There are two courses of action here:
I’d go with the second option. There are two ways to do this as well. First you could manually encode the image data to base64 and append the proper data URL prefix for it, like this:
Alternatively you could use a blob and the createObjectURL function. Sadly these are experimental stuff and I haven’t been able to make it work yet. However the code is a bit cleaner and should be more efficient. It should look like this:
I really hope that there will be support for this later on. Of course you can always just point your image’s src to your image somewhere on your server. However there are cases where this approach is not viable (such as mine was).
When you’re doing modern JS development you’ll spend lots of time at the command line. You will constantly need to run stuff like acquiring packages, unit tests, minification and the rest.
The Windows command line is capable of doing the job, you’re better off with a more advanced solution. I would recommend using ConEmu which is a great substitution of cmd. It can handle multiple tabs which is quite a life saver. Of course there are lot more features, be sure to check it out.
Although I won’t write much about Node.JS we will be using its packet manager NPM. The two are linked together in one download. Go over to the download page of Node.JS and get the proper version.
After the installation go to your %APPDATA% folder. If everything is set up properly you should see an npm folder there (the whole path is supposed to be Users/username/AppData/Roaming/npm). Add this npm folder to your PATH variable.
Git is a distributed version control system which is pretty popular. Since lots of people are using it and most JS packages are maintained in git repos on GitHub we’ll be using it as well.
You can download git from Git-scm.com or just the GitHub client for Windows. Either way, make sure that git.exe is in your PATH.
After git is installed you can test it by just typing
git in your console and see the help page emerge. Be sure to do this before you proceed, since Bower will be using git internally.
Bower is a package manager for client-side web development stuff. Although you’ll find lots of packages in NPM as well it is mainly intended to be used with Node.JS. To install Bower we will use NPM. Open up a command line and type the following command:
npm install -g bower
You might figure it out that this command installs Bower to your system. It’s very important to use the -g switch which means that the package is installed globally. It will be placed to the npm folder you just added to your PATH so you’ll be able to work with Bower ASAP.
To test if everything is working properly create a new folder somewhere, point your console to that folder and issue the following:
bower install jquery
If everything went well you should see a newly generated folder
bower_components and within it the latest version of jQuery. But using Bower this way is not leveraging its full potential. You would get the packages but would not get the mobility.
You need to configure Bower by adding a bower.json file to your project root. This file will contain some information about your project, and all the packages that Bower needs to use. You can generate it using the
command. Don’t worry if you don’t understand something, just hit enter and Bower will use reasonable defaults.
The main point of interest in a bower.json file is the list of dependencies. There are two main types – normal and dev dependencies. Normal dependencies are everything that your final product uses and requires to function. Like jQuery or Bootstrap. Dev dependencies are stuff that you need to develop your application but the app doesn’t depend on them. Like Jasmine and Karma for unit testing.
You don’t need to edit your bower.json file by hand every time you add a new dependency. There are two switches that update this file. If you are adding a normal dependency then use the –save switch:
bower install jquery-ui --save
If you are adding a dev dependency then use the –save-dev switch:
bower install qunit --save-dev
Now you have a solid setup with all the necessary tools to start working on your project. Although we’re far from finished – part 2 will cover Grunt, the JS task runner, and part 3 will deal with the extensive options of unit testing JS code. Stay tuned!
I won’t be lying to you that stuff came to be an abomination. It was relatively simple stuff. We needed some dialog with a searchable tree inside it and some extra features I don’t really remember. Well I worked, sweat and delivered. The result was your typical thousand lines long unmaintainable ball of spaghetti covered in mud and crap. But it worked so that was nice.
Since then I spent a lot of time figuring out how to do JS properly. I even gave a presentation about it which pretty much shared the characteristics of my first JS project. I’m not a talker guy and it showed. Anyway I learned a lot by myself and had even better guidance from people vastly more knowledgable than me. So I present some action items to you so you don’t have to learn them the hard way.
This is perhaps the most important thing. If you ever attempt to write maintainable JS code you need to split your stuff into smaller files. Don’t write all your code into a single file. Also don’t mix HTML and JS in one file, use references.
You should also keep your files short. One hundred lines should be enough for most use cases. You can even use a JS dependency manager, like RequireJS.
There are volumes of literature written about testing – especially unit testing – code. JS given its dynamic nature provides enormous flexibility – and the same breadth of errors. Since there’s no compilation with type checking you can easily invoke function which doesn’t exist causing a runtime error.
This is my favourite kind of error I use to make – writing the function
getParameterByName and then trying to invoke
getParamByKey in other places. Tests are great to catch this. And also a lot of other errors.
And be sure to actually run those tests. There are great unit testing tools in JS like Karma, a test runner, Jasmine or QUnit, unit testing frameworks. There’s also the great browser PhantomJS which is written for JS testing and automation.
There are numerous best practices and anti patterns in JS accumulated over the years. Some of these can be validated by other code, called a static analyser. Do yourself a favour and use one. I’d recommend JSHint for this purpose. It’s pretty strict by default, but you can obviously fine-tune its behaviour.
Basically all it does is that it goes over your code and checks if you do something in a less than ideal way. Like not declaring variables or using undefined functions by mistake.
Much has been written in JS and much is being written in this very moment as well. Sure you can write it better but you don’t have to. You should be focusing on providing value for whoever you write that code for.
So use what is already there if it fits. To do that, you can use Bower, a package manager for client-side JS. The usage is easy, you just type
bower install this_awesome_package and Bower takes care of resolving and storing the files.
You just need to push the configuration file to source control, so that others can download the same packages with Bower, without requiring to keep lots of third party code in your repository.
You don’t want to do all common tasks by hand (unit testing, running JSHint, minifying your code, etc). Everybody hates these recurring and menial tasks, so let your machine do them for you.
Get Grunt, a task runner for JS. You’ll find tons on predefined tasks (like running your Jasmine tests with Karma on a PhantomJS browser outputting coverage data) and you save precious time where you can create value instead of getting frustrated with your toolset.
Seriously this shouldn’t even be a step. Setting up a git repo is super simple, so you should have one. And if you don’t like git there are tons of other alternatives, most of them free.
This is obviously more advanced stuff, but a proper build process is a must have when there are other people working on your codebase. I would argue that even if you’re just by yourself you would benefit from running a build every time you commit code.
Your build process should validate your JS code (a la JSHint), run your tests and publish the result to some place where you can check it for yourself.
On the other hand I learned tons of new stuff. I can only compare the current knowledge gaining to the very beginning of my career, when I started to learn C# and ASP.NET.
The reason I write this post is twofold. First, I want to propagate the idea of abandoning your well-known technology stack for a while to learn something entirely different. I believe there’s succinct and fundamental diversities between the C# and the JS world. It successfully moved me out from being stuck in a warm and fuzzy world with little uncertainty. It also opened lots of new opportunities.
The other reason is that I plan to write some follow up posts on the more intricate stuff that was quite a pain to figure out in the current cutting edge JS stack. To name a few, I got the chance to work with AngularJS, RequireJS, Node, NPM, Bower, Grunt, Karma, Jasmine, etc. I also had the opportunity to get into a more intimate relationship with functional programming practices and JS per se.
Brace yourselves, complete stack change is coming.