I've gotten very good at talking myself out of doing any side projects. Finding flaws and planning for failure, the qualities that help me a lot at work, don't let me believe in my ideas enough that I would take them to life.
On the other end of the spectrum is the hopeful entrepreneur making a classic mistake, developing a product before confirming she has a verifiable edge over the competition, and solves a problem real people have. Edward Thorpe said it the best in “A Man For All Markets”: in business, just like in gambling, you only play when you know that you'll win.
I decided that for some current ideas, as well as new ones that I consider viable, I'll withhold judgement. Instead of gauging whether the product would work, I'll take it unconditionally to the landing page stage. It takes almost no commitment and creates no technical debt, it's just a domain and some static HTML. It's a win-win from any point of view: I spend much less time on it than building the simplest MVP, writing a description forces to be precise about the idea and its details, and I can show the result to people, perhaps potential users.
You don't even need a landing page. Market research should come first in talking to your future users. But my ideas usually have me as the user, so I can make the first pass without talking to people.
I'm working on a project right now, and I'll add a link to it to the Projects section soon.
It's too easy to get into the habit of consuming by default: check email, Twitter, Facebook, Slack, Basecamp or a million other services designed to consume our attention. It's funny how “consuming” works both ways.
Producing by default, when you have to restore lost context to continue writing or programming, or drawing after switching away, is much harder, but it's a habit just like any other. Initial friction will go away and you won't feel resistance starting to re-explore your own, not someone else's, ideas.
I see that a lot in myself when starting to write code in an unfamiliar language. My intention is to write the best code I can. In order to do that, I need to read a guide, best practices, examples and try and build a mental scaffolding that will help me produce the code that I want.
But it's too easy to be stuck in the “research phase” as it's called, never doing the work. How am I going to be fluent in a language if I don't practice producing it? How am I going to produce if I don't know how to do that?
There's a catch. Reading leaves few traces in your mind, and when the time comes to write, you feel like gripping thin air, nothing comes out. Try writing the simplest things, make mistakes, no one is judging. Code is meant to be rewritten anyway.
Sounds simple? I get caught often. Just when I think I learned enough, I try writing and find I forgot almost everything that I've read. What was the point of reading then? I could spend that time writing, encountered the problem and would have read the answer the same way.
Ads are the best thing about old computer magazines. These are from the August 1979 issue of the BYTE magazine about LISP.
At the time those computers were considered powerful, or at least capable, and now, 40 years later, we buy chips with similar specs wholesale for $1 or $2 to power some kind of IoT device, and they're considered severely underpowered for any real embedded work. Our WiZ Wi-Fi connected lamps use a chip with similar specs, an ESP8266, made popular because of a free RTOS and low price, but even that has 96 KB RAM, a 50% increase.
High end servers have RAM in the terabytes, a hundred million percent increase from these 1978 chips.
What I wonder, looking at the present-day magazine ads, praising laptops to be thin, light, and powerful, is just how peddling, thick and underpowered they will seem in forty years' time. Even more suprising is that we do feel they are genuinely light (just under one kilo!) and thin (just 9 mm thick!), exactly the same as we felt about laptops of ten years ago, which have been twice as thick and twice as heavy.
The only constant thing about consumer computers is that a good one always costs $2000.
It's a faux pas to write on your blog about how long you haven't written on the blog. I wonder who taught me manners.
Last time when I stopped publishing for a while was when I took on a new job at Ungert Design. This time it's a new job too, and the break stretched for a year and a half.
Work hasn't become boring, on the contrary, working on WiZ brings some challenges that are worth spending time to solve. It's just time to write again.
I have much to share, I haven't been not writing all this time, it was just not public.
One of the things I practise often is writing down app ideas. If you have your eyes open, there are a lot of them. And I wrote down a lot of them too, the list is now more than a hundred. I have a separate list for apps, but I also write down more general product ideas. Some projects aren't worth a second look, some keep me thinking for months.
I thought that I could share the ideas on the blog as I'm having them, and some of the better ones from the backlog.
The first one is posted, and more will follow under the tag Product Ideas.
Sometimes, when you're on the go, you just want a smaller photo. Your cell signal isn't very strong, you want to snap and share something unimportant and delete the photo afterwards, or you don't want people on the internet to read notes scattered on your table that you shared on your social network of choice, or maybe you're abroad and want to conserve bandwidth on your tourist SIM card.
iOS will let you resize a photo only when you're sending an email, but don't we share photos on messengers much more often? You can also start an editor, load the photo in it and resize manually to a specific size, then save it to the Camera Roll, go back to Photos.app and share it from there. Sounds a bit tedious.
Low Res Photo is an app with just four buttons: Snap, Select, Save, Share. Yes, “choose” is better, but I want my extra S!
Snap a photo or Select it from the library. Save the smaller version of the selected image or Share its resized version.
There are no size or ratio or scale controls. The image is resized to be 800 px on its largest size, or not resized if it's smaller than that.
Why not write about some of the books I read in January? Honestly, thinking about writing a post about some of my reading prompted me to read more, so it's a good thing and I'm planning to keep up the habit.
“Functional Swift” by Chris Eidhof, Florian Kugler and Wouter Swiersta of objc.io
I believe it was called “Functional programming in Swift” recently, but when the book was updated in December 2015 for Swift 2.1 (which I read) it got renamed as well, and for the better.
This one read a lot like the Apple's official Swift book for me: clear, concise, to the point and at the same time introductory. The book consists of several sections exploring different topics e.g. writing a wrapper for Core Image or implementing a test suite which generates tests automatically, all of them revolving around the functional approach to solving problems.
If you're interested in the actual functional programming, reading “Learn you a Haskell” would be more beneficial, but if you're curious how to think differently while writing in Swift or learn some new approaches to common problems, it's a great introductory book that you can later supplement with more reading on the topic, having the primaries down.
“Turning Pro” by Steven Pressfield
This is a small but intense book intended for everyone who is (or should be) hard at work. I read it last time three years ago, worked a lot since then, and this time it stood out even brighter than before. It's a great reminder why you would jump out of bed each morning and work hard. A motivational book, so to say, but not in a happy way — a sobering one: the work is hard and it's you who has to do it, no exceptions.
Here's my slightly longer review on Goodreads if you're interested.
The final two books are (surprise!) about financial markets and specifically, high-frequency trading. Why read them over crunchy programming books? December saw the launch of Stockfighter, a game where you basically write a trading bot to try and game the simulated financial market. Yes, this is supposed to be someone's idea of having a good time, and incidentally I had a good time designing and (partly) writing my own library for it. Anyway, on to the books.
“Flash Boys” by Michael Lewis
Lewis is a good writer and writes a good story, but when it comes to the technical details… not so much. Some glaring holes right there, and far more than once I was close to making a facepalm.
Still, it's probably the best book to start with on this topic as it paints the picture in large strokes and gives you a good idea of the emotions behind what people were doing. You can read any number of technical books on the subject, there are many, but first you have to dive in and look around, and this is a really good introduction that starts slow and holds you by the hand all the way in.
Yes, some claims are outrageous and plain wrong, but it's entertaining and Lewis gradually explains most of the buzzwords you're likely to encounter in other books about the subject.
Don't confuse it with “Flash Boys: Not So Fast” by Peter Kovac which is sort of a bashing reply to Lewis. Kovac too makes quite a lot of mistakes, judging by the reviews, so I haven't read it yet.
“Dark Pools” by Scott Patterson
This is another “introductory”, or rather, non-technical book, which looks at the same process described in Lewis' “Flash Boys”, but from a different angle. Where Lewis mostly follows the story of a banker playing catch-up to high-frequency trading firms, Patterson describes the lives of several prominent people who directly influenced the rise of HFT from the inside. Small shops which eventually grew to enormous size and changed the market altogether.
Arguably, “Dark Pools” is far more technical of the two and I really enjoyed reading it. It's more technical, but it's still a story, so it's perfectly readable and just as entertaining: Patterson goes into a lot of detail on how the markets worked since the early 90s up to the current moment. It also turned out to be more applicable to Stockfighter: quite a few of the actual techniques he describes used by high-frequency traders I can see used in the game verbatim.
Reading about HFT is surely nice, but I decided that I should stop reading and beat a few levels of the game first :)
After reading “Profiling your Swift compilation times” I decided to try it for our project, as it's about 80% Swift and a couple of Objective-C frameworks. Frankly, dry compile time (after cleaning) is just really bad, pushing 3 minutes. Most of the time compilation is incremental and takes much less time, but the project has to be cleaned several times a day anyway, and the compile times add up.
If the linked post ever goes away, you can profile your project simply by adding the following to your Other Swift Flags in Build Settings for the intended target:
After that you do the following to get the output file culprits.txt with sorted function compile times:
xcodebuild -workspace Project.xcworkspace -scheme Project clean build | grep [1-9].[0-9]ms | sort -nr > culprits.txt
Here's an edited excerpt from our project before I started optimizing:
1172.0ms Views/BeaconMeasurementDataTableViewCell.swift:17:10 func configure(beacon: FilteredBeaconData) 1053.3ms Controllers/ClientViewController.swift:855:20 @IBAction @objc func canvasViewTapped(sender: UITapGestureRecognizer) 994.2ms Helpers/CLLocationDistance.swift:35:17 public func region() -> String? 978.2ms Helpers/CLLocationDistance.swift:35:17 public func region() -> String? 928.3ms Controllers/ClientViewController.swift:855:20 @IBAction @objc func canvasViewTapped(sender: UITapGestureRecognizer) 782.2ms Helpers/CGRectSquare.swift:24:10 func canBeInsetBy(x: CGFloat, y: CGFloat) -> Bool
As you can see, the worst function takes just over a second, and some functions get repeated, so you can edit them once for multiplied benefit. In total, there were about 70 lines with functions taking longer than 100 ms to compile. Here's the before:
$ time xcodebuild -workspace Project.xcworkspace -scheme Project clean build real 15m41.535s user 24m43.824s sys 2m59.478s
I decided to not spend much time on this as we had a different situation than the linked post's author and were not likely to get much improvement. So I edited about 10 worst functions (and found a couple of missed bugs in the process, which is an added benefit). Then I ran the test again:
real 13m7.661s user 22m24.623s sys 2m46.180s
Not much, but that is still a measurable difference: 16.3% for real, 9.4% for user and 7.4% for sys, so about a 10% improvement in total. Not bad for an hour and a half of work.
I also tried comparing the difference in compile time from Xcode when running the app on the simulator, but couldn't come to a definite conclusion: even after cleaning, Xcode compile times vary a lot and the total time stayed around the same 3 minutes. Of course, it's much faster when the libraries and some modules are already cached, usually the build takes no more than 10-15 seconds.
I encourage you to test this for your Swift project if you're disappointed with compile times, it may well be a quick and big win.
Some fascinating reading this week!
First, the New York Times asking “Why are the corporations hoarding trillions?” where they claim Apple, Google and other giants don't spend or convert their cash, as if expecting something just beyond the horizon. Something that would need an insane amount of money.
Second, Ben Goertzel with “Superintellingence: fears, promises and potentians”, a through and in-depth review and criticism of current literature by Bostrom, Yudkowsky and others.
This struck me as amusing:
As Peter Norvig of Google has noted (personal communication), quite suddenly we’ve gone from outrage at the perceived failure of AI research, to outrage at the perceived possible success of AGI (Artificial General Intelligence) research!
For the last decade, AI research and theory is booming, and it's very hard to ignore the fact that every other app or service now has some form of machine learning or AI-like capabilities, the most common example being Siri on iOS. There are many more examples, like Google Now or various personal assistants like AlfaSense, X.ai or even something as simple as a blog layout system.
Very excited to see the progress.
Behind the scenes it is using swift build — the build option available only in the open-source toolchain so far. The errors are the same that you can find in Xcode, and Syntastic makes them available with line marks and both command window and location list. Though I have an option set which prevents the location list from opening automatically, it can only close if there are no more errors:
let g:syntastic_auto_loc_list = 2
Sadly there is no autocompletion yet. There is decent support via SourceKitten but it's only working for Xcode projects. I only have Package.swift :)
I wrote a UISplitViewController category for our app USpace which makes it behave in a slightly different way: it collapses to the right and has a wide “master” portion. When expanded on iPad, it looks like this:
I chose UISplitViewController over a custom solution because the app is universal and has to support everything from the same codebase: iPhone, iPad and iPad split-screen mode, and switch and rotate seamlessly. Another constraint is that it has to be rotation-locked on iPhone (i.e. the app should always be in portrait mode) but at the same time show a specific controller in landscape mode, which prevents us from using the Info.plist interface orientation restrictions.
Most of the custom solutions on GitHub that implement a slide-out horizontal menu do it in a very primitive way, by having a parent controller that slides two views around. USpace view hierarchy is much more variable and complicated to use such a solution, and on top of that, most of them only support iPhone. Besides, I'm a big proponent of rolling your own solution first, to test the water and figure out what features you would actually need. More often than not, you quickly end up with a minimal solution that a) fulfills all your needs b) works perfectly c) is easy to maintain.
We move pretty fast, and my first task was just to create a slide-out controller not unlike one you see on iPad when you swipe from the right side of the screen. It's called Slide Over if I'm not mistaken. So I just presented a full-screen overlay with a thin controller on the right, and with a bit of work it was working both on iPad and iPhone and was customized to our needs. We quickly grew out of it, setting up the expected view hierarchy was finicky, so I decided to switch the whole app to a UISplitViewController. It took a few days to iron out all the problems (did you know you could put a navigation controller inside another navigation controller in a specific way and have two working navigation bars on top of each other?) but finally it worked, and worked beautifully.
Today I was trying to fix one of the last bugs with this approach, and it was… strange. If you hold the iPhone horizontally (remember that the app is rotation-locked, so everything is sideways) and try opening that one controller which should be displayed in landscape mode, the navigation controller you're pops your current visible controller and only then presents the landscape-controller. In code it's just a simple presentViewController(_:). Here's a sample lldb output:
(lldb) thread backtrace * thread #1: tid = 0xb08ed2, 0x00000001859e2008 UIKit`-[UINavigationController popViewControllerAnimated:], queue = 'com.apple.main-thread', activity = 'send gesture actions', stop reason = breakpoint 1.1 * frame #0: 0x00000001859e2008 UIKit`-[UINavigationController popViewControllerAnimated:] frame #1: 0x0000000185bce11c UIKit`-[UINavigationController separateSecondaryViewControllerForSplitViewController:] + 148 frame #2: 0x0000000185e48104 UIKit`-[UISplitViewController _separateSecondaryViewControllerFromPrimaryViewController:] + 360 … frame #27: 0x000000018592dcec UIKit`-[UIViewController presentViewController:animated:completion:] + 184
I quickly figured out that when trying to present the new controller the app window rotated to landscape orientation and it prompted the wrapper UISplitViewController to split its “secondary” view controller — without asking me, apparently! I made a dive into the docs, and lo and behold, right there on the UISplitViewControllerDelegate page it said:
When you return nil from this method [ splitViewController(_:separateSecondaryViewControllerFromPrimaryViewController:) ], the split view controller calls the primary view controller’s separateSecondaryViewControllerForSplitViewController: method, giving it a chance to designate an appropriate secondary view controller. Most view controllers do nothing by default but the UINavigationController class responds by popping and returning the view controller from the top of its navigation stack.
We're very interested in the last sentence, because that is exactly what was happening. This only happened on iPhone in landscape layout, because on iPad it didn't have to split this way, or rather, it did, but it had no effect because the view hierarchy was different when it was allowed.
Still, that was not the end. I returned nil most of the time from the method mentioned in the docs, but this time I had to return a view controller if I didn't want the navigation controller to pop. I could also subclass the navigation controller (but it's not future-proof and cumbersome) or prevent it from popping in the navigation controller delegate, but it would be far from the place where the action originated, and the split view controller delegate approach allowed me to keep control in the same file, so there you go.
What I ultimately did is returned a “dummy” view controller from the “splitting” method and and did a return true for this case in the “collapsing” method. What return true means is that you tell the system that you have done what was necessary and you need no further action on its part. Basically it gives you a view controller and says: “Hey, I want to collapse this!” and you reply “Don't worry, I did everything myself!” while doing absolutely nothing. This way the “collapsing” view controller is just dumped and you never see it again. Again, if you let the system do its job, it will push this controller on top of your navigation controller in the “master” controller.
All in all, it was a fun bug to resolve. Hopefully my explanation maybe helps someone out there :)