Oleg Andreev

Month
Filter by post type
All posts

Text
Photo
Quote
Link
Chat
Audio
Video
Ask

January 2011

NFC and payments with a phone

Why are people so obsessed with the NFC buzzword?

The only safe and understandable way to conduct the payment with a phone is with the protocol like this:

1. Shop sends a payment request to your bank (via shop’s bank or directly)
2. You bank pings your phone and waits for confirmation.
3. You take your phone out and confirm the payment. You can do this securely over Wi-Fi, 3G, EDGE, Bluetooth, NFC and any other communication technology which lets you to speak TCP/IP and finally (after going through all the proxies and routers) connect to the Internet.
4. When bank gets the confirmation, it acknowledges the transaction and tells the shop about it.
5. Shop issues a ticket and you walk away.

This protocol is safe (contrary to modern credit card processing) because you never trust someone else’s device (you trust only your phone) and you never give away any secret information (like credit card number or a PIN code).

The only tricky thing here is how to give the shop your banking ID (which can be a phone number), so they can send it to your bank which will contact you for confirmation. This can be done in many different ways:

0. Tell the ID to the shop assistant - simple to understand, but needs remembering and typing in. Since we need a phone to confirm payment anyway, we don’t even count it.

1. Show the barcode on the phone’s screen and scan it. You need to launch a payment app anyway. Why not to display you bank ID as a barcode on the first screen so you can simply scan it.

2. Use NFC to announce your ID to the shop. This like barcode scanning, but without optical scanning. It has its issues, though. If you have many devices nearby, the receiver may confuse your device with someone else’s, or recognize your slower. Everybody knows how slow bluetooth is.

3. Do it in reverse with NFC: the shop will publish you bill and (if you are lucky) only your phone will see it, so you can send it to your bank.

To me, the most usable ways to conduct payments are #1 and #2. And #1 seems to be simpler and faster (but feels “lo-tech”).

Bottom line is: NFC is not a requirement for payments with a phone. You need any communications tech to connect to your bank and can use different ways to announce your banking ID.

I also hope, that the phone payments won’t be done in the same way as credit card processing is done. That is, by giving away secret codes and trusting the shop to confirm the transaction.

Jan 27, 20111 note
MacAppStore and external distribution

Gitbox started selling in November using old-school method: download a free version from gitboxapp.com, then upgrade to a paid version by buying a license.

Today Gitbox is available on Mac App Store as well. What this means to you?

If you have already purchased Gitbox, you don’t need to “connect” it to App Store. First, it is impossible to do for free: you’ll have to buy it again, from Apple. Second, you won’t miss much. Gitbox is a single-version application: there is no “lite”, “full”, “appstore” or “non-appstore” variant. The functionality is all the same. (Only difference is that binary in appstore has different autoupdating and license checking mechanisms.) Gitbox already provides automatic updates for free. There is one nice feature of the non-appstore purchase: updates can be released within minutes instead of a week.

Note that App Store marks the app as “installed” if it sees it on disk even if it was never downloaded from Apple. If you want to purchase it from Apple (maybe you have not yet purchased a license), then you should drop the app to Trash and restart App Store: the purchase button will become available. Your preferences won’t be affected.

So how do you decide where to purchase an app? Both distribution channels are great: appstore is more controlled, but sometimes much more convenient, another one is more flexible, but less integrated into OS. I believe it is important to keep both options available to you, but I want to avoid any confusion. So here is my policy:

1. Prices and discounts will always be the same and synchronized for both stores. The app is the same, hence the price is the same.

2. I will do my best to release big updates synchronously on both stores. I usually don’t release more often than once a week or two, so it is very possible to adjust to the appstore review delays.

3. In case of security updates or critical bug fixes, I will post an update immediately even if the appstore does not publish it as quick as I do on my website.

Enjoy Gitbox and buy it where you like. You will get the same support and love everywhere.

Jan 6, 20111 note
#appstore #gitbox #policy
Adding custom views to NSCells

How do you add a view (spinner, text field, button etc.) into the cells of NSTableView or NSOutlineView?

Simple:

1. Keep a reference to the view in your NSCell.
2. In drawInteriorWithFrame:inView: you should create the view if needed and add to the controlView if needed. controlView is provided as a second argument to this method.
3. Position the view according to the cellFrame (first argument to the drawing method).
4. Do not forget to retain or nullify the view in copyWithZone method. Remember that copy and copyWithZone copy instance variables as-is without retaining object pointers when you might need that.

Correction on January 6th, 2011:

There is no point in keeping a reference to a view in the cell. After the cell is drawn it is often deallocated immediately, so the view will stay visible forever. You need to keep the reference to the view in some external non-volatile object: a view, a view controller, or a model.

Jan 5, 20112 notes
#cocoa

November 2010

Gitbox 1.0 released

I’m happy to announce that Gitbox reached its first major milestone: a first commercial release. It is a great version control app for working with Git repositories. Instead of cutting down the powerful, but complicated concepts of Git, Gitbox embraces them with a truly elegant user interface. Many people start actually using branches in Git thanks to Gitbox.

Download Gitbox 1.0 now. Use coupon GITBOXNOV before December 1st to get 30% discount.

Since the last preview version, a lot of things have changed. I have worked out a strong vision of what kind of product I want to create. As a part of it, I have redesigned the user interface and reengineered the underpinnings. Now all the repositories live inside a single window and the app itself is running on Grand Central Dispatch (GCD) on Snow Leopard. Translation: Gitbox is faster and easier to use.

A couple of thoughts on licensing policy: usually commercial software comes in two flavors: a full and a trial. Here’s the problem: when I download a trial version it is usually limited to 14-30 days of free use. I may try the software for a couple of minutes, then put it aside and forget about it until I have a real need in it (or some very handy feature is released). When I come back to the newer version, it appears I cannot try it any longer!

Gitbox does not do that. You may try it right now and for as long as you want. You also have all the features available with only one fair limitation: only one repository opened at a time. Why is it fair? Because if you don’t find Gitbox useful enough to pack it with all your repositories and use it every day, I don’t want your money. Instead, I would be happy to listen to you and make it better.

When you do buy a license, you get more than you paid for. First, all updates are free (some really cool features are coming soon). Second, you may use the app on all your machines without any sorts of spyware, activation etc. The only limitation is that the license is for personal use. If you want to buy Gitbox for a group, you should buy an appropriate number of individual licenses. Contact me if you’d like to get a discount in that case.

I will release new features and incremental design improvements regularly in a form of free software updates. As the app becomes more powerful and better designed, the price is likely to rise. Since the updates are free, this idea should convince you to buy a license early at a lower price ;-)

I’m very thankful to my family, colleagues at Pierlis and all the folks who were using preview versions and giving a lot of priceless feedback.

Let’s get it started.

Nov 27, 20102 notes
#gitbox
OOP and business

In a software business, the functionality is an asset, but code is a liability. The less code needs your attention, less costs and risks you have.

OOP is all about making stuff work, packaging it into an object with as small interface as possible, and building other stuff around without going back and tinkering with that package. Note to Java people: it does _not_ mean the object should fit everything. It should fit at least a single task and be reliable at that task. The point is in reliability, not reusability.

This concept is called “incapsulation”. It is not the way to make the code nice. It is the way to minimize your costs and risks and finally ship.

Nov 18, 20103 notes

October 2010

Splay tree

“All normal operations on a binary search tree are combined with one basic operation, called splaying. Splaying the tree for a certain element rearranges the tree so that the element is placed at the root of the tree.

A top-down algorithm can combine the search and the tree reorganization into a single phase.”

http://en.wikipedia.org/wiki/Splay_tree

The splay tree modifies itself every time it is searched becoming more and more efficiently organized over time.

Oct 31, 20103 notes
A copy-pastable code

Everyday as a software developer you have to invent some abstractions. Simply speaking, you have to decide where to put the new code. After you decide this, you write more code and repeat the process. Sometimes the earlier decisions need to be changed and you refactor the existing code. Now you decide where to put the old code.

I really need a hint. The OOP folks teach us to model the real world. Just look at the problem domain, they say, and you will see where the things belong. It works great until you hit some system-specific pure abstractions and there is no natural metaphor to help you.

Try another approach. Since the initial question is where to put the code, and the refactoring is about moving the code around, why not to make the code itself easily movable? How about making the code copy-paste friendly?

The first idea which comes to your mind is to wrap it in the object. Yes, it might solve the problem. But at what cost? Creating an object means defining the interface (class, protocol, whatever) which creates another entity in the program and eats a part of your brain. Not always a good idea when you are already stuck finding out where’s the best place for just ten lines of code.

When you are trying to solve a problem, do not hurry creating another one. Relax, put the code somewhere where it is easier to move from and make it depend on the nearby code as little as possible. Usually you do so by putting the dependent data in some local variables. You can later transform them into function arguments or object properties.

When you make the code movable, you can (sic!) move it around and isolate more and more over time. Maybe 5 minutes later you will discover you don’t need it at all. Or that it should be simplified and moved in a function. Or that it should have more functionality and become an object. Or that it should be split in two different tasks. All of these questions become much easier to answer when you keep the code simple, stupid, light and isolated just enough. Just enough to copy and paste it.

Oct 30, 20105 notes
A history of concurrent software design

Early approaches to concurrency

When machines were big and slow, there was no concurrency in software. Machines got faster and people figured out how to make multiple processes running together. Concurrent processes proved being extremely useful and the idea was brought further to the per-process threads. Concurrency was useful because it powered graphical interactive applications and networking systems. And those were becoming more and more popular and more advanced.

For some tasks concurrent processes and threads presented very difficult challenges. The threads participate in a preemptive multitasking, that is the system where the threads are forced-switched by the kernel every N milliseconds. At the same time, the threads has a shared access to the files, system interfaces and in-process memory. The threads do not know when they are about to be switched by the system, which makes it difficult to safely retain and release control over the shared resources. As a partial solution, different sorts of locks where invented to make multi-threaded programs safe, but those didn’t make the work any easier.

A typical code in a multi-threaded environment:

prepareData();
lock(firstResource);
startFirstOperation();
unlock(firstResource);
prepareMoreData();
lock(secondResource);
startSecondOperation();
unlock(secondResource);
finish();


Modern concurrency

Next approach to concurrency was based on a realization that the problem of shared resources lays in the very definition of the “shared”. What if you create a resource with a strictly ordered access to it? Sounds counter-intuitive: how can this be concurrent? Turns out, if you design the interface like a message box (that is only one process reads it and nobody blocks waiting for a response), you may build many of such resources and they will work concurrently and safely. This idea was implemented in many sorts of interfaces: unix sockets, higher-level message queues and application event loops. Finally, it found its way into the programming languages.

Probably, the most wide-spread programming language today, JavaScript, features function objects that capture the execution state for later execution. This greatly simplifies writing highly concurrent networking programs. In fact, a typical JavaScript program runs on a single thread, and yet it can control many concurrent processes.

Mac OS X 10.6 (Snow Leopard) features built-in global thread management mechanism and language-level blocks making writing concurrent programs as easily as in JavaScript, but taking advantage of any amount of available processing cores and threads. It is called Grand Central Dispatch (GCD) and what it does is perfectly described by a “message box” metaphor. For every shared resource you wish to access in concurrent and non-blocking way, you assign a single queue. You access a resource in a block which sits in the queue. When the block is executed, it will have an exclusive access to the resource without blocking anybody else. To access another resource with the results of the execution, you will have to post another block to another queue. The same design is possible without blocks (or “closures”), but it turned to be more tedious and limiting and resulting in less concurrent, slower or unstable programs.

The modern concurrent code looks like that:

prepareData();
startFirstOperation(^{
  prepareMoreData();
  startSecondOperation(^{
    finish();
  })
})

Every call with a block starts some task in the other thread or at a later time. The block-based API has two major benefits: the block has access to the lexically local data and executes in a proper thread. That is it eliminates the need for explicit locks or moving and storing the local data explicitly just for making it available in a proper thread.

Think of it this way: every block of code inside the curly brackets is executed in parallel with the code it was created in.


Future directions

The upcoming generation of software already is or will be written this way. But block-based approach still isn’t perfect. You have to manage queues and blocks explicitly. Some experimental languages and systems already have a transparent support for “continuations”: that is the code looks linear, in a blocking fashion, but the process jumps between different contexts and never blocks any threads:

prepareData();
startFirstOperation();
prepareMoreData();
startSecondOperation();
finish();

This is much more natural and looks like a naïve approach which we started with and fixed with the locks. However, to make it work concurrently we have to learn GCD and take it to the next level.

When you start some operation which operates on a different resource and can take some time, instead of wrapping the rest of your code within a block, you put the current procedure in a paused state and let the other procedure to resume it later.

Imagine that instead of the discrete blocks of code, the kernel manages continuously executed routines. These routines look very much like threads with an important exception: each routine gives up the execution voluntary. This is called cooperative multitasking and such routines are called coroutines (рус. сопрограммы). Still, though, each routine can be assigned to a thread just like a block or be rescheduled from one thread to another on demand. So we retain the advantage of the multi-processing systems.

Example: you have a web application which does many operations with shared resources: reads/writes to a database, communicates with another application over the network, read/writes to the disk and finally streams some data to the client. All the operations should usually be ordered for each request, but you don’t want to make thread wait each time you have some relatively long-running operation. Also, it is not efficient to run multiple preemptive threads: there is a cost of switching the threads and you get all sorts of troubles with random race conditions. GCD and blocks help for the most part, but if you use them to make every single operation on a shared resource, you will get an enormously deep nested code. Remember: even writing to a log means accessing a shared file system which better be asynchronous.


15 years later

Today, a lot of trivial operations like writing to a disk or accessing a local database do not deserve asynchronous interfaces. They seem fast enough and you still can drop more threads or CPU to make some things faster. However, the coroutines will make even these trivial tasks asynchronous and sometimes a little bit faster. So why is that important anyway?

The coroutines are important because every shared resource will get its independent, isolated coroutine. That means, every resource will have not only private data and private functionality, but also a private right for execution. The whole resource will be encapsulated as good as any networking server. The file system, every file, every socket, external device, every process and every component of an application will have a coroutine and a complete control on when to execute and not execute. This will mean that there is no need for a shared memory and a central processor. The whole RAM+CPU tandem can be replaced with a GPU-like system with hundreds of tiny processors with private memory banks. The memory access will become much faster and the kernel will not need to waste energy switching threads and processes.

A single design change which makes programming easier will make a shift to much-much more efficient architecture possible. It won’t be just faster, it will be efficient: while the servers could be 100 times more productive, the personal devices could be 10 times faster while consuming 10 times less energy.


30 years later

By the time operating systems will support coroutines and a truly multi-processor architecture, new applications will emerge with capabilities we can only dream about. Things like data mining, massive graphics processing and machine learning work mostly in the huge data centers. Twenty years later this will be ubiquitous just like a 3D games on the phones today. These task will require more memory space. Finally, the common storage memory will be merged with RAM and processor and processing of huge amounts of data will become much more efficient.

Given such a great advance in technology, humanity will define its unpredictably unique way to educate and entertain itself. As we get closer to that time, it will become more clear what is going to be next.

Oct 29, 2010
Two kinds of charts

There are two very different kinds of information visualizations. And I don’t have pies and bars in mind.

The first kind is for presenting the knowledge. You have already discovered some interesting facts and now need to present them clearly to the reader. Your task is to design a most appropriate form for the data, that the knowledge will become obvious. (Of course, you should not be dishonest and lie to a reader by making perspective distortions or shifting the zero point.) Sometimes you may even drop the figures and just show the data geometrically. The charts should have little noise: no lines, no ticks, no labels. Curves can be smooth and some nice 3D effects can be applied. Present as little data as necessary. Prefer geometric objects to tables.

The second kind is for discovering the knowledge. You have raw data and no particular idea about what could be so interesting about it. In such case you need a format which lets you discover the knowledge. Comparing to the first kind of visualization, here you might want to have more additional information, most probably an interactive table or graph to play with. Add some additional hints: the mesh, absolute and relative values, confidence intervals etc. Of course, this form should be much more honest and complete than the presentation of a first kind. No special effects, no smooth curves. Prefer tables and simple charts to fancy geometric objects.

When presenting a data, first thing to do is to decide what kind of problem do you solve. If you present a raw data, make it easy to work with it and find the knowledge. If you have already found a knowledge, present it in the most clear form.

Oct 28, 2010
Printed book idioms to be avoided on screen

1. Breaking an article into multiple pages.

Page is a physical limitation of a paper medium. Sometimes the text does not fit and you have to drop the last paragraph on another page. On the screen you have plenty of vertical space and there is no excuse to cut the reader’s context.


2. A lot of iPad newspaper apps simulate multi-column layout. They shouldn’t.

The purpose of a multi-column layout is to make articles’ layout more flexible on a big newspaper page. On a wide page you can fit a couple of articles and an ad. But the screen is not that wide.

Narrow columns also require small font size, which is a problem on a display of a resolution under 300 dpi.

Narrow columns require manually-tuned hyphenation and sometimes font width-adjustment. It is a requirement for the books as well, but a more narrow column looks even worse. Unfortunately, it is not the case for the digital media today.

If the column does not fit the screen, you constantly have to scroll down and up when reading a page: down when finishing the first column and up to proceed to the next one.

You can scroll and zoom the page on screen. If you make a single scrollable and zoomable column, you don’t need to provide font size control or worry about how much of content is visible. The reader can choose the more comfortable size of the page for herself.


3. A lot of people use footnotes on the web. This is horrendous: you have to leave the current line and scroll down. And even if you scroll by clicking a footnote number, you then have to scroll back. And even if you have a link from the footnote back (like in a wikipedia article), browser doesn’t scroll exactly to the position at which you were before.

On the screen you have a plenty of vertical space. And if you don’t use multiple columns (which you should not), you have some space on the side. That means, you may put some notes in the block of smaller font right below the paragraph, or on the side.

Summary

Do not break articles in pages. Do not break text in the columns. Make text column scrollable and zoomable. Make the footnotes immediately under the paragraph, or put them on the side.

Oct 25, 20103 notes
Mac OS X Lion predictions

There are some predictions or wishlists floating in the tubes regarding an anticipated update to Mac OS X. Some of them are more probable, some less and some are just plain crazy. Let me give you my predictions and some commentary.

1. The next cat name is likely to be “Lion”. This is based entirely on a single picture from the invitation picture and also is the least interesting prediction. I don’t think it is going to be the “last” release in any sense.

2. The merge with iOS. First, Mac OS X already has some UI features borrowed from iOS: navigation buttons in Dock stacks, iPhoto and iTunes. There will be more of them. Maybe scrollview will be updated with more flat scrollbars, maybe some bouncing will appear (and if so, it will be off by default for the existing software).
No way there will be a touch-controllable UI for the existing applications. The apps are not designed at all for the multi-touch and the size of the finger. Even if Windows 7 supports this, there’s no reason for Apple to follow the same path. However, taking in account the dual-mode touch screen patent, it seems more probable that Mac OS X might be transformed into iOS device on demand. But Apple does not favor dual-mode UIs: this just creates confusion for users and developers. The Front Row is a rare example of a second UI mode (transforming Mac into a focused media player). But the iOS is considered more or less a full-feature environment with far reacher user interface then the Front Row and at least as rich as Mac OS X. It is very unlikely that the iMac or MacBook will have two personalities which complete with each other and cooperate badly producing a huge confusion.

So believing in a strong movement towards touch UI everywhere, we may expect not a dual-mode, but per-window fusion of the iOS apps into Mac OS X. This has it’s issues also: still the file sharing is not as smooth as what we expect on a desktop OS, the iPad screen in portrait mode does not fit in the MacBook screen. And again, if you can touch and drag the iOS window, why not to touch and drag other windows? And if you can touch and drag all the windows, why not touch all the buttons? And the screen should be oriented horizontally just as keyboard or trackpad today. This is not easy to solve.

So the UIKit multi-touch will eventually show up in some version of Mac OS X, but it is not as easy as some may believe. The less improbable prediction: the Mac OS X will have a very conservative, slow introduction of touchscreen with emphasized limitations to minimize confusion as much as possible.

3. AppStore for Mac OS X. This is a really good idea in pure form, but once again has some conceptual difficulties. Apple will not lock the Mac OS X as they did with iOS, so it will compete with other distribution channels and may be forced to lower their 30% cut. At the very same time they would have to retain approval process to filter out crappy software they will sell. Developers who are not happy with the commission and the approval process, will go distribute the apps on their own. But this is very hard to debate because there’s still no third party app store for Mac, so the place seems vacant. Or it is vacant because no one could build a viable store business yet. Anyway, the Apple is the most likely company to succeed at this, and if executed perfectly, it will attract a lot of developers and make themselves and Apple much more money, and drag the Mac even further in the market share race.

4. Resolution independence (making UI 1.25-1.5 times bigger). Mac OS X team works on resolution independence for more that 4 years already. And still, on Snow Leopard the implementation is buggy and far from being anywhere close to “beta” status. The conceptual problem here is that this technology is aimed at scales of 1.25 and 1.5, not 2.0 like on iPhone. And this is not as simple as multiplying everything by two. I guess the displays with 2x higher resolution (for MacBooks at least) will become affordable before the 1.25 scale will be fixed for all the shipping apps.
Oh, do not forget that the “retina display” approach does not make things bigger for people with poor vision, it makes them sharper. The sharper text somewhat easier to see, but not as easy as 1.5x bigger one. Apple may realize that system-wide smooth resolution scaling is not worth tinkering with and full screen zoom is just enough for solving vision problems. My bet is on retina displays and old resolution independence framework being put on the shelf.

5. Finder improvements. Some folks dream about tabbed Finder. The problem is that file system is hard enough already. Adding tabs just complicates the look of the Finder and makes file system even scarier. Even if the tabs find their way into Finder, they will be disabled by default. Just like the tabs in the earlier versions of Safari were disabled.

What would be really cool is a merge of the Dock Stacks with the Quick Look and a merge of Quick Look with other apps. This is a pure speculation. Have you noticed how easy it is to jump through the folders in the Dock Stack? Buttons are big and once you find the file you want, the window disappears automatically. The Quick Look also disappears easily. Finder on the other hand, creates clutter: you have too many individual Finder windows all over the desktop. The tabs do not remove the clutter, they just organize it. Maybe what we need is not organizing it manually, but having something like a “recent folders” list and jumping through them using Quick Look.

How many times you’ve started a movie in Quick Look and played it way too long to forget that it is not a stand-alone player? And then you do something with Finder and the movie disappears! Take a look at the iCal: if you open an event, the popover window will appear with details. This window behaves much like the Quick Look: do something else and it disappears. But if you move is a little bit, it will transform into a stand-alone panel which will stick on the screen until you close it. The same idea can apply to Quick Look. It will be super-useful to transform a folder preview into a Finder window, a movie preview into a Quick Time window etc.


6. iChat with FaceTime, iCal like in iPad, iLife, iWork updates: this all is possible. The question is the timing: maybe not all of that will be tomorrow, but only some. I don’t expect super-cool features here, but more like an evolution and improvements.


7. Macs won’t support blu-ray drives. I haven’t heard about blu-ray from any of people I know. Those who really need it may buy an external drive.


8. There won’t be NTFS mounts or built-in VM for Windows. Not because there is a fight with Microsoft. Apple simply doesn’t have time for the features most people don’t need. BootCamp was an important thing in 2006 to bring more customers. Nowadays Apple does not mention “switching” anymore. There is already a plenty of ways to communicate with Windows, both built-in and supplied by third parties.


9. Mac OS X distributed as a free software update. Recently Apple has lobbied an accounting rules change to be able to distribute free updates of iOS for non-subsidized products like iPod touch and iPad. This makes the platform more vibrant and much more devices stay up-to-date. Making Mac OS X update free, Apple can accelerate adoption of their technologies and bring better and more exciting applications to the Mac.

Edit: forgot to add that a lot of goodies from UIKit, MapKit, EventKit etc. might well be ported to the Mac APIs. The NSTableView might learn about recyclable views from UITableView.

Oct 19, 20102 notes
#predictions

August 2010

Don't mix concerns: objects and things

Don’t tie external resources lifetime to object lifetime (for instance, file descriptors). Never start any process in constructor/initializer. Have “start” and “stop” methods (or “open”/“close”) dedicated for managing the resource.

Don’t mix data construction and performing a procedure. Whenever you have a method which takes 10 arguments, it is time to create a separate object just for that procedure. Give it 10 properties and a “start” method. Later you’ll be able to add more configuration options and alternative invocation APIs to this object in a clean way.

In general, when you begin understanding OOP, you tend to treat everything as an object. Data structure, complex procedure, network connection, physical device — all become objects. The trick is while you incapsulate all those things into objects, you shouldn’t confuse the *object* with the *thing* it manages. The object is a manager, driver for the thing, but not the thing itself. Object may have language-oriented API and thing-oriented API. Don’t mix them. First API lets you to create, initialize, inspect, destroy object. It must have no impact on the thing. To manipulate the thing, you write thing-specific methods.

Quick test for compliance: you should be able to instantiate a valid object, set properties in any order, inspect it and destroy without any effect on other objects and things around.

Aug 26, 201011 notes
#mixing concerns #oop

June 2010

Gitbox

Gitbox is a nice little interface for Git. I wrote it primarily for myself and my friends to optimize everyday operations. Go download the app from the website and come back here for details.

Gitbox displays each repository in a little separate window. Each window has 3 parts: branches toolbar, the history and the stage.

Toolbar makes branch operations a lot simpler. You always see which branch you are on and which remote branch is associated with it. Branch menus let you checkout existing branch, a new branch, remote branch or a tag.

The history shows commits for both the current local branch and remote branch. Commits which are not pushed yet have a little green icon, so you will never forget to push your changes. Commits on the remote branch which are not yet merged (pulled) are marked with a blue icon and a light-grey text. And you may switch remote and local branches to compare them.

Stage shows the changes in the working directory. You may stage and unstage a change using checkboxes or just select changes you want to commit and press “Commit” button.

Gitbox updates stage status every time you focus its window and fetches remote branch commits while in background.

Gitbox will be free for a limited amount of time. Prices and conditions will be announced later. Check for updates regularly!

Follow Gitbox updates on twitter @gitboxupdates.

Please send questions, bugs and suggestions to my email address: oleganza@gmail.com (or twitter)

Jun 7, 20106 notes
#git #gitbox #release

April 2010

Crash-Only Softwareweb.archive.org

“Crash-only programs crash safely and recover quickly. There is only one way to stop such software – by crashing it – and only one way to bring it up – by initiating recovery.”

“It is impractical to build a system that is guaranteed to never crash, even in the case of carrier class phone switches or high end mainframe systems. Since crashes are unavoidable, software must be at least as well prepared for a crash as it is for a clean shutdown. But then – in the spirit of Occam’s Razor – if software is crash-safe, why support additional, non-crash mechanisms for shutting down?”

Apr 14, 2010
#crash #robustness #complexity
Designing for iPad: Reality Checkinformationarchitects.jp

iA writes about over-realistic design of iPad apps. I guess, it’s only a beginning: a way to catch attention. As with Mac OS X, Apple and other developers will gradually remove unnecessary pieces as people get more familiar with the device.

Apr 12, 20101 note
#ipad #design
Knight's Principles

Knight’s Principles

— Never do any work that you can get someone else to do for you

— Avoid responsibility

— Postpone decisions

— Managers don’t do any real work

— Premature optimization leaves everyone unsatisfied

— Try not to care

— Just do it!

— It’s not a good example if it doesn’t work

— Steal everything you can from your parents

— Cover your ass

“Each object will do a seemingly insignificant amount of work, but somehow they add up to something much larger. You can end up tracing through the system, looking for the place where a certain calculation happens, only to realize that the calculation has been done and you just didn’t notice it happening.”

Apr 10, 20101 note
#oop #principles #knight
Is iPad an autonomous device?

When you buy one, the first thing you see is “Connect to iTunes” screen. You need some “big” computer to start using it. If I’d like to buy one to my grandma, who does not have and cannot use a modern desktop computer, I have no problem with initial setup using my macbook.

The only way to back up your data is, again, to connect to iTunes. Most of the apps keep the data on the server (btw, I hate when people say “in the cloud”), but you still have photos, notes and documents on the device. I don’t know whether MobileMe and iWork.com actually back up the data or just share selected files, but they could be easily extended to do just that later when more people will try to use iPad as a primary device, not just as a “node in a digital hub”. Right now, mobileme offers e-mail hosting which can also synchronize notes. But current version of iPhone OS does not offer notes sync using e-mail account (while Mail.app on Mac OS X does).

If my grandma has a problem with her iPad she might lose her pictures and notes. However, my grandma particularly is not going to take much photographs and notes, so that is not much of a problem.

As of now, the only obstacle to making the iPad an only computer in the house is to get rid of big-brother iTunes requirements by replacing it with a internet service to do the very same thing. I bet Apple is moving towards making iTunes a 100% capable web application in addition to desktop version.

Apr 4, 2010
#ipad #itunes

March 2010

Programming songs

Monzy — Kill dash nine

Coder Girl

IE is being mean to me

Write in C

Zed Show — Matz Can’t Patch (show text)

I woke up this morning,
to look around at the tubes.
I saw neither was working,
I got the Matz Can’t Patch blues
Twitter’s down
37’s too.
I got the fuckin’ Matz Can’t fuckin’ Patch fuckin’ motherfuckin’ blues
‘Cos Matz can’t patch, Matz can’t patch
(Oh, singing like blues guys sucks!)
Matz can’t patch.
I walked down the street
I saw Matz: why do you pend the patch, what is your fuckin’ problem? We wanna the patch, because, hey…

“I’m fucking Matz, ain’t gonna patch.
Patching’s for squares.
Patching… I don’t dare.
Patch, don’t, whatever.
Because I’m Matz.
And Matz don’t patch.”

And then he just walked away.
Mar 28, 2010
#songs #programming
“

I could hardly believe how beautiful and wonderful the idea of LISP was [McCarthy 1960]. I say it this way because LISP had not only been around enough to get some honest barnacles, but worse, there wee deep flaws in its logical foundations. By this, I mean that the pure language was supposed to be based on functions, but its most important components — such as lambda expressions quotes, and conds — where not functions at all, and instead are called special forms.

Landin and others had been able to get quotes and cons in terms of lambda by tricks that were variously clever and useful, but the flaw remained in the jewel. In the practical language things were better. There were not just EXPRs (which evaluated their arguments), but FEXPRs (which did not). My next questions was, why on earth call it a functional language? Why not just base everything on FEXPRs and force evaluation on the receiving side when needed?

I could never get a good answer, but the question was very helpful when it came time to invent Smalltalk, because this started a line of thought that said “take the hardest and most profound thing you need to do, make it great, an then build every easier thing out of it”. That was the promise of LiSP and the lure of lambda — needed was a better “hardest and most profound” thing. Objects should be it.

”
—Alan Key, The Early History of Smalltalk (1969)
Mar 22, 2010
#key #alan #oop #lisp
Pitfalls of lack of encapsulation

Tony Albrecht, Technical Consultant at Sony, tells a story about memory performance and object-oriented programming style.

If you read the story carefully, you will notice that the performance problem was actually solved by writing class-specific allocators (that keep each object of the same kind in a continuous array) + doing recursive algorithm in two passes.

Tony knows very well what happens on hardware level, but he is not good at object-oriented programming. Let’s see what is wrong with his code.

In the beginning, their code is not well organized: instead of multiple distinct objects with small independent data structures they had fat nodes with matrices, vectors and other structures built-in. Because of that, the various kinds of data were interleaved and didn’t play well with the cache.

First optimization: they made the code object-oriented by factoring big data structures like Matrix and Vector out of the Node. Then, they used the incapsulation (fundamental principle of OOP) to provide custom allocators with continuous memory zones. This is only possible in a proper object-oriented code when objects of one kind do not interfere with objects of another kind other than with explicit messages. So you can optimize memory layout for Matrices, provided their behavior is not changed, and you will not break some other part of the code. OOP helped to gain 35% of performance.

Second optimization: they splitted the recursive update procedure into two phases to avoid going bottom-top adding WBS (world bounding sphere) more than once per parent node. This would save about 25% of CPU time (assuming binary tree and no overhead on leaves). But they actually got about 50-60% increase because they used continuous allocator for nodes like they did with matrices and vectors.

This is all understandable. But there are two design decisions which are not justified:

1. In the first optimization Tony claimed that “excessive encapsulation is BAD” (slide 20) and thus decided to put raw pointers to the array of matrices and vectors outside of their respective nodes into the loop which iterates over the nodes (slide 89):

for (int k=0; k < innerSize; k++, wmat++, mat++, bs++, wbs++)
{
*wmat = (*parentTransform)*(*mat);
*wbs = bs->Transform(wmat);
}

Do you see those wmat, mat, bs, wbs pointers? These are private things pulled out of node objects under the claim of “excessive encapsulation is BAD”. Now object does not control its data and once you’d like to add another special-effects matrix over the node, you’ll have to learn not only the Node class, but the entire rendering codebase!

This is how it should be done actually:

for (int k=0; k < innerSize; k++)
{
children[k]->updateWithParentTransform(*parentTransform);
}

Where updateWithParentTransform does the job involving wmat, mat, wbs and bs and gives you guarantee that this is the single file where these variables are accessed directly.

Also note that this method will be perfectly inlined by C++ compiler or smart dynamic Smalltalk/Self/JVM system, so the result code will do the same operations and memory accesses as the manually inlined code with “naked” private pointers.

2. The second claim is to “Make the processing global rather than local” (slide 73). This is also awfully wrong. Tony suggests splitting the tree of nodes into arrays of nodes sorted by level. It is not only inflexible (or requires quite complicated algorithms to maintain the invariant), but is also pointless.

We already have these class-specific continuous allocators which put nodes close to each other. We already have extracted huge data structures from the nodes, so that we may keep a lot of nodes in just a fraction of the L2 cache while the rest of it is used for matrix operations. And we already split up the algorithm so that the parent’s boundary is not updated too often. But still, he claims some performance gain out of the fact that nodes are not traversed recursively, but rather linearly using quite a brittle memory layout.

There is no point in that since node objects are so small that most of the data you need to update children using parent’s transformation matrix is already in the cache. And for the cached data there’s no difference how it is positioned: the access time is constant.

But he did not only traded nothing for more complicated code, but also made his life harder to move from a single CPU to multiple CPUs (say, GPU): only recursive algorithms and encapsulation may give you an option to parallelize computation. By flattening algorithms and breaking encapsulation Tony cut himself a way to scale the performance horizontally (or, equally, made it harder to automatic parallelizing compiler to do its job).

It is very important to know how things work on low level, but is also important to know how to incapsulate low level complexity and free your mind for greater deals.

Update: Tony replied showing that I’m not entirely right. (March 18, 2010)

Mar 16, 20102 notes
#oop #sony #slides #pdf #memory #performance #incapsulation
“[Computing] is just a fabulous place for that, because it’s a place where you don’t have to be a Ph.D. or anything else. It’s a place where you can still be an artisan. People are willing to pay you if you’re any good at all, and you have plenty of time for screwing around.”—Alan Key, 1972 Rolling Stone article.
Mar 13, 20103 notes
#alan key #quote #computing #artisan #phd

February 2010

“The only way to write complex software that won’t fall on its face is to build it out of simple modules connected by well-defined interfaces, so that most problems are local and you can have some hope of fixing or optimizing a part without breaking the whole.”—The Art of Unix Programming
Feb 22, 20102 notes
#art #unix #modularity #book
“One important distinction is client vs. server. ‘Client’ translates as: being lightweight, suppporting only a single user, able to run on small machines, designed to be switched on when needed and off when the user is done, lacking pre-emptive multitasking, optimized for low latency, and putting a lot of its resources into fancy user interfaces. ‘Server’ translates as: being heavyweight, capable of running continuously, optimized for throughput, fully pre-emptively multitasking to handle multiple sessions. In origin all operating systems were server operating systems; the concept of a client operating system only emerged in the late 1970s with inexpensive but underpowered PC hardware. Client operating systems are more focused on a visually attractive user experience than on 24/7 uptime.”—The Art of Unix Programming
Feb 22, 20102 notes
#unix #book #ipad
Android vs. iPhone: the good, the bad and the ugly

In last two months I had an opportunity to build two versions of the same application: on iPhone and Android. Both applications are basically navigation/tableview-based browsers for existing French website. Absolutely nothing extraordinary about the whole thing, but it is interesting how similar features could be accomplished on competing platforms.


The Good

First of all, you don’t have to register or pay a fee in order to start developing and testing on a device. Also, you may work on Windows and Linux, but I have not tried that out.

There’s a very flexible layout framework which allows you to position elements relative to each other, to the parent and to the content. You may wrap layout around its content, but also tell it to fill N% of free space. Or fill the whole parent width (or height). Android layout are much more flexible and still simple comparing to Cocoa and even HTML+CSS. Even though the Eclipse IB-like plugin sucks, XML layout language is easy to learn and is not hard to type.

Layouts seem to be simpler and more light-weight than iPhone views: in iPhone I have to render tableview cell by hand (all these tedious pixel calculations: paddings, margins and conditional layout depending on missing text) to maintain smooth scrolling; on Android an straight-forward XML layout for a cell was enough. This is a real time-saver.

Resolution-independent metrics are very powerful: you have regular points and pixels (device-dependent), device-independent points (dips) and device- and textscale-independent points (sips). Elements with dip-dimensions will be sized equally on different screens and elements with sip-dimensions will scale according to user preferences.


The Bad

The first bad thing about Android is Java. Though it is not a language or VM. It is the way people write Java code. They do it fundamentally complicated in every single place. My application does not have any sophisticated features. It is damn simple. And iPhone has simple tools for that. Android and Java have tools to build a space shuttle.

Every single thing in Java (and I’m speaking about both legacy java.lang.* and modern android.* APIs) makes you use a couple of classes and a couple of interfaces. The classes themselves usually inherit 4 levels of superclasses and countless interfaces. In sake of code reuse, the core functionality which you use on a single object is usually split across several classes which makes you switch between various doc pages enormous amount of times. This creates a great pressure on developer’s brains: in process of building a 5-minute feature you have to load your head with almost useless hierarchical structures.

Java developers would say that on the other hand you have a rich reusable toolkit. In fact, the simple thing like network connectivity (parse url, asynchronous download over http, setting and reading http headers) could not be done using a single doc. In iPhone I’ve build a little handy OAHTTPQueue around just a couple of Cocoa classes: NSURL, NSURLRequest and NSURLConnection. I was learning Objective-C and Cocoa from scratch and it took just a couple of hours to implement a descent queue. When I switched to Android I already knew what I’m going to build and how should it work. But it took almost three days to get through 3 (!) huge independent packages android.net.*, org.apache.http.* and java.net.*. Each package had some useful bits on its own, but none was easy to take and build something right away. None contained a simple asynchronous API. Finally, I got to take single thread executor from java.util.concurrent and use a blocking HTTP API from org.apache.http. Other options were as high-level as writing to a socket by hand. The devil of Java is very well illustrated by apache HTTP library: not only it has tons of classes and interfaces, these classes are scattered across 10 sub-packages. In Cocoa you can do all the same things with about 20 NSURL* classes, using 3-4 (!) of them 90% of the time.

In average, for each Cocoa class there are 10 classes and interfaces in Android providing about the same functionality. In other words, Cocoa is 10 times more productive than Java.

Android lacks good programming guidelines. With that amount of options Java spits on you, the guidelines are absolutely a must.

It seems, Google does not care much about the phone. I got lots of stupid errors in MapView. It also lacks built-in pins, annotation pop-ups and callbacks for region-changing events! I had to implement pins and pop-ups by myself. And without useful callbacks, there’s a repeating timer which polls MapView properties and triggers a callback after user stopped dragging/zooming the view.


The Ugly

UI is slow and does not feel right. Scrolling momentum is not natural, every screen opens with a noticeable delay, maps are slow and some screens are 16bit. (Hello, it is 2010 already!)

Android device has physical buttons. Only 2 of them wake device from sleep: “menu” and “hang up”. Others are no-op. Very confusing.

Every application has a hidden menu. It pop-up when you click a “menu”, which is a physical button. And then you have to click a screen button. And to go back from wherever you are you have to tap a physical button again.

Android is over-engineered and under-designed platform. It has interesting model of multitasking stack of activities, but it fails completely when it comes to actual UI. There are “back” and “home” physical buttons. Pressing “back” removes current activity from the stack. Pressing “home” pushes Home Screen on top of the stack. All running activities remain in memory. And when you tap application icon from the home it opens the top-most application activity.

There are 3 lists of the applications: on the home screen, on the “placard” which slides over home screen and somewhere in the Settings (where you should go in order to remove an app). When you remove an app from the home screen it is not clear that you are not going to erase it completely (same issue with Dock on the Mac).

I gave HTC Tattoo phone to several people around me: everyone got confused by the navigation.


The End

Android UI is ugly, slow and complicated. Google is happy to put its apps and a search box in the system, but they are not interested in phone sales. Mobile carriers are interested in having an iPhone competitor, but they do not produce anything. Finally, manufacturers from China do not care about UI and global market strategy, they just produce devices.

Apple, on the other hand, is interested in both device sales and app sales. And they care about the whole chain: from hardware to end-user services.

Android seems to be dying already.

Feb 3, 20103 notes
#android #iphone #good #bad #ugly #google #htc

January 2010

Admin pages

The average web-based shop works like this: there’s a front and a back. The front is sexy, the back is not. One group of people goes to the front to buy stuff, other group goes to the back to manage that stuff. These groups of people intersect only when those who go to the back pretend they are buyers. But still, there’s a huge distinction.

On the other hand, the real shop also has a front and a back. But those who sell stuff do not stay in warehouse all day long turning knobs to rearrange stuff on shelves. They actually go to the shop room to put things in place, see how they look and how customers explore them. In other words, a physical shop is more WYSIWYG than a web-based one.

My suggestion is to outsource to warehouse pages as little functions as possible. The shop owner should have a control on what is presented to the people. He should be able to immediately update prices, titles, rearrange things and see some basic stats which help to decide how good something sells.

Jan 31, 20103 notes
#webdev #admin #design #ui
Idea: Web browser for work

I’m using Safari because it is fast, simple and not ugly. But it has several annoying issues:

1. It does not return allocated memory back to system (however, it recycles it internally and does not leak). I end up with Safari eating 1+ gigs and multiple windows with multiple tabs opened. And it is not easy to restart Safari due to a second issue:

2. It does not remember opened windows and tabs automatically. If I opened 10 tabs to read later (or to work with), I have to save them in a bookmark group. And it is not easy to remove/add new pages to that bookmark group.

3. Even if I have enough memory and Safari does not crash too often, I still have multiple windows and tabs, and hidden tabs. It is hard to switch between them, especially using a keyboard.

Let’s see what we can do about it.

First, I turn to other applications I use every day: Mail, TextMate and Xcode.

In Xcode and TextMate I have a quick access to any file using a Cmd+T shortcut: I press Cmd+T, a small window pops up with a search field. I type a portion of file name and it appears in the list. Press Enter — and here it is.

Cmd+T is useful for rare switching. For more frequent switches there’s Alt+Cmd+Up to switch between .h/.m files and Alt+Cmd+Left/Right to navigate through tabs in TextMate.

In Mail I have an Inbox and the folders. Inbox contains unread/undone messages. Everything else is in the folders.

In Mail I also have a single window with a single list of items. If I want to open a particular message in another window, I double-click on an item.

With some background I may draw some requirements for a browser useful at work:

1. It should always remember all windows positions and opened websites. If it crashes, it should restore all pages as they were opened before crash. (Just like Opera did for many years, by the way.)

2. It should have a Cmd+T menu to have a quick keyboard access to all open and bookmarked pages.

3. It should remember history for a page even if it is opened in a new window or tab.

4. The unread pages should be marked so.

5. There should be a context menu item “Read Later” which puts the link into Inbox and marks it as unread.

6. It should cache all the bookmarked pages on disk (in a form of webarchive) for indefinite amount of time. Each new version should be stored as well, but not overwrite the previous one. I want to access exactly the same content I’ve once seen.

7. Closed pages should be easy to reopen. (Safari lets you reopen a window, but not a tab).

Next step is to make some UI mockups to see how silly (or not) these desires are.

Jan 31, 20102 notes
#safari #browser #xcode #textmate #mail #ui #idea
Interfaces in dynamic object-oriented languages (part 2)

In the first part I suggested to use messages like to_my_interface or asMyInterface to ensure interface-compliance. This method just returns whatever object seems to be suitable for the interface, but does no actual checks. IDE like Xcode or Eclipse can do a static check for implemented methods and issue warning/error at compile time. Today I will show how to build the same feature in the dynamic system (and make it more useful).

First, two important points from the first part:

One object (sender) send a message to another (receiver) with an argument which should implement String interface (receiver will call asString method on its argument).

1. The sender does not need to perform any “casting” before sending an interface-compliant object. If appendString(obj) wants a string and you know that your object can (or should) behave like a string, you just pass it in without any conversion. Only low-level method which relies on actual string methods like substring should send asString to obtain the String interface.

2. The receiver should not perform any checks like respondsToSelector or isKindOfClass. It should only tell the argument to return something with an interface it needs.

If both sender and receiver do not check actual interface compliance, where should it happen? Obviously, inside the asString method:


# this method does not check the interface
def asString
self
end

# this method checks the interface
def asString
String.check(self)
end

How’s that different from just testing application as before? First of all, check is performed before any protocol message is send to the subject. So it is more like a “compile-time” check: some message could not be sent in runtime, but the error could be thrown before.

In addition to basic checks like missing methods String.check can also perform some unit tests (and be smart enough to test each particular class (hidden class) only once).

Needless to say that interface checks could be omitted in production mode to increase performance.

Jan 8, 2010
#oop #protocol #interface #unit testing #tdd #design
"4 columns for soft news, 5 columns for hard news"informationarchitects.jp

Tages Anzeiger redesign suggestion.

Jan 1, 2010
#design #newspaper #redesign #text #paper
Flatlandignorethecode.net
Jan 1, 20101 note
#flatland #ui #gui #hierarchies #design

December 2009

What Colour are your bits?ansuz.sooke.bc.ca

“Bits do not naturally have Colour. Colour, in this sense, is not part of the natural universe. Most importantly, you cannot look at bits and observe what Colour they are. I encountered an amusing example of bit Colour recently: one of my friends was talking about how he’d performed John Cage’s famous silent musical composition 4'33” for MP3. Okay, we said, (paraphrasing the conversation here) so you took an appropriate-sized file of zeroes out of /dev/zero and compressed that with an MP3 compressor? No, no, he said. If I did that, it wouldn’t really be 4'33" because to perform the composition, you have to make the silence in a certain way, according to the rules laid down by the composer. It’s not just four minutes and thirty-three seconds of any old silence.“

Dec 29, 2009
#bits #law #crypto #copyright #xor #link #quote
“The original codename for Direct X was “the Manhattan Project,” because strategically it was an effort to displace Japanese game consoles with PCs and ultimately the Xbox. We called it “The Manhattan Project” because that was the codename for the program developing the nuclear bomb. We had a glowing radiation logo for the prototype for Direct X, and of course as soon as that got out and the press covered it, it caused a scandal.”—Interview with Alex St John
Dec 17, 20091 note
#directx #microsoft #logo #xbox

November 2009

Why you should avoid Out Of Memory checksarticle.gmane.org

“So in summary, OOM-safety is wrong:

- Because it increases your code size by 30%-40%
- You’re trying to be more catholic than the pope, since various
systems services you build on and interface with aren’t OOM-safe
anyway
- You are trying to solve the wrong problem. Real OOM wil be signalled
via SIGKILL, not malloc() returning NULL.
- You are trying to solve the wrong problem. Make sure your app never loses
data, not only when malloc() returns NULL
- You can barely test the OOM codepaths”

Nov 23, 20091 note
#malloc #code #oom #unix #maillist
Nov 22, 20093 notes
Start with algorithms

— I find OOP methodologically wrong. It starts with classes. It is as if mathematicians would start with axioms. You do not start with axioms - you start with proofs. Only when you have found a bunch of related proofs, can you come up with axioms. You end with axioms. The same thing is true in programming: you have to start with interesting algorithms. Only when you understand them well, can you come up with an interface that will let them work.

— Can I summarize your thinking as “find the [generic] data structure inside an algorithm” instead of “find the [virtual] algorithms inside an object”?

— Yes. Always start with algorithms.

An interview with Alexander Stepanov, author of STL

Usually you start deciding what components your application consists of, then you write some code to glue them together. Later, you face a change in the requirements and start “fixing” the object model with a scotch tape. When you run out of tape you finally redesign your object model to fit the algorithm. Otherwise, if you focus on the algorithm instead of data structures, you’ll spend less time on (re)writing the code.

OOP, however, is orthogonal to this idea. Objects still encapsulate code (algorithms) and data (requirements). Requirements are set through the object’s interface. The only difference is that you should design objects from the algorithms perspective, not the abstract data relations. This is why relational database should be normalized, tuples should have as little number of fields as possible, object should do only one job etc.

Nov 15, 20091 note
#algorithms #methodology #oop #stl #c++ #cpp
Kaganov on security

Very good post (google translation) on airport security improvement and security strategies in general.

Nov 3, 20091 note
#kaganov #security #russian #airport

October 2009

object.or { default_value }
Little helper to deal with nils, empty strings and arrays. class ::Object def blank?; false end def or(default = nil) blank? ? (block_given? ? yield : default) : self end def and blank? ? nil : yield(self) end end class ::FalseClass def blank?; true end end class ::NilClass def blank?; true end end class ::Array def blank?; compact.empty? end end class ::String def blank?; strip.empty? end end class ::Hash def blank?; values.empty? end end Examples: " ".or "Untitled" # => "Untitled" " ".or { calculate_value } # => "42" [nil].or { ["apple", "orange"] } # => ["apple", "orange"] "data".and {|data| Wrapper.new(data) } # => wrapper " ".and { ... } # => nil
Oct 29, 20091 note
#blank? #ruby #snippet
Elastic tabstops suggestion by Nick Gravgaard (with demo!)nickgravgaard.com

I would also suggest treating 2+ spaces as one or more tabs to avoid tab vs. spaces debates. See also my article on DSSV.

Oct 27, 2009
#dssv #tabstops #link #formatting #code
“

In college computer science classes, we learn all about b*trees and linked lists and sorting algorithms and a ton of crap that I honestly have never, ever used, in 25 years of professional programming. (Except hash tables. Learn those. You’ll use them!)

What I do write – every day, every hour – are heuristics that try to understand and intuit what the user is telling me, without her having to learn my language.

The field of computer interaction is still in its infancy. Computers are too hard to use, they require us to waste our brains learning too many things that aren’t REAL knowledge, they’re just stupid computer conventions.

”
—On Heuristics and Human Factors by Wil Shipley.
Oct 23, 20092 notes
#wilshipley #quote
How Key-Value Observing (KVO) is actually implemented at the runtime levelmikeash.com

Thanks to @groue for the link

Oct 23, 20091 note
#groue #link #kvo #objc
What's the difference between a "disc" and a "disk"?support.apple.com

Thanks to Pierlo for the link.

Oct 23, 20094 notes
#apple #disc #disk
How Clang blocks are implementedcocoawithlove.com

“If you’re familiar with how Objective-C objects are declared […] blocks are Objective-C objects. This may not seem strange in Objective-C but the reality is that even in pure C or C++, blocks are still Objective-C objects and the runtime support for blocks handles the retain/release/copy behaviors for the block in an Objective-C messaging manner.”

by Matt Gallagher

Oct 19, 2009
#objc #clang #blocks #link #http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
Oct 18, 20092 notes
#slides #google #performance #distributed
DRY and evolution

When you up to implement a feature similar to what you already have, there’s a huge temptation to refactor and abstract existing code right away. Sometimes you even have a perfect idea how it should be done.

Nevertheless, Don’t Do That.

Take an existing class, copy it, rename and update to meet your needs. Test, tweak, test again. You will see clearly how it is different from the original code. Don’t rush to extract common code, let yourself test/tweak more. Of course, don’t let it stay unDRY for a long time: it may become hard to refactor them later when you forget what you were actually doing.

In other words you should let your code evolve in a natural way like Darwin prescribed. Replicate and mutate the code: you will see better solution among the options. Then according to the Rule Of Survival Of The Fittest delete everything not worth living.

In many-many cases this technique helps to avoid wasting time on fitting code into wrong abstractions built on pure imagination.

[Blames himself for the mistakes of the past.]

Oct 16, 20093 notes
#dry #refactoring
How to perform requests from Rails app to itself without hitting HTTP servergist.github.com
Oct 16, 20091 note
#gist #rails #howto
Unit testing is teh suck, Urrwilshipley.com

“You, as a programmer, should be programming EVERY LINE as defensively as possible. You should assume that every other method in the program is out to kill you, and they are intentionally passing you corrupted buffers and pointers, and it’s your job to handle all that crap and make the best of it. (And, if you can repair it, do so, and if not, raise an exception so you can catch it in beta testing, instead of silently failing and/or corrupting data.)”

@wilshipley

Oct 14, 20091 note
#unit testing #defensive #quote #link
Indie Software Security: A ~12 Step Programchargen.matasano.com

“Here are five things that will kill your startup before software security does:

— Slowness
— Poor graphic design
— XML
— The RIAA
— Product Marketing Managers

The graveyards in this town are littered with the corpses of startups that pinned their hopes on advanced security. Better engineers than you have tried and failed. Theo de Raadt coordinated the first large-scale security codebase audit. His reward: Only two remote holes in the default install!”

Article
Slides

Oct 13, 20091 note
Paper: sRuby - A Ruby dialect for low-level programmingthekode.net

This is an evolving document describing sRuby, a subset of Ruby that can be easily compiled to fast low-level code. The purpose of developing sRuby is to use it to implement a Ruby virtual machine. However, we anticipate that it can be used to write Ruby extensions that needs to bridge the gap between Ruby and a low-level language © in an easy and portable way.

Robert Feldt
April 4, 2001

Oct 12, 20092 notes
#ruby #vm #paper
The efficient way to load and render images in the UITableViewCell

Suppose you have that kind of user interface:

The efficient rendering algorithm would be the following:

1. Cell should render its content manually: that is not using multiple views, but using a single contentView which is updated programmatically in drawInRect: method.

2. Each time cell is rendered, it checks the cache of downloaded images. If image is not present, cell schedules request to download it. Cell should remember the request URL to be notified when data is ready.

3. Download request goes to FILO queue with async NSURLConnection delegate. Async API uses the main thread which is notified when data is ready.

4. The queue size should be limited by a maximum number of visible cells. The most recently requested images go to the end of the queue, while the head of the queue is truncated each time new request is added. This way scheduled requests are removed when corresponding cells become invisible.

5. Download callback should lookup [tableView visibleCells] to find the exact cell which requests the downloaded image. The cell could be different than the one started the request (remember cell recycling!). You cannot just call [tableView reloadData]: it works poorly when a lot of images are loaded while you scroll.

6. In addition to downloaded images cache, there should be pre-rendered images cache: each time cell draws itself and finds the downloaded image, it should rescale and crop the image. The rescaled image should be put in the cache, otherwise scrolling won’t be smooth. Of course, if the downloaded image is already sized as needed, this step could be omitted. See UIGraphicsBeginImageContext.

Toolkit summary:

— download requests queue with async i/o (no NSOperations, no background threads)
— manual cell rendering (no subviews)
— individual cell update (do not reloadData)
— pre-rendered images cache
— discard pending downloads for invisible cells

Oct 8, 20092 notes
#iphone #rendering
Avoiding races with Unix signals and select()xs4all.nl
Oct 8, 2009
#signals #unix #i/o #select #networking
The devil's guide to choosing new mathematical terminologycr.yp.to
Oct 7, 2009
#guide
Next page →
20152016
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
201420152016
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
201320142015
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
201220132014
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
201120122013
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
201020112012
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200920102011
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200820092010
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200720082009
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200620072008
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200520062007
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200420052006
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200320042005
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200220032004
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200120022003
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
200020012002
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199920002001
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199819992000
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199719981999
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199619971998
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199519961997
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199419951996
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199319941995
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199219931994
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199119921993
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
199019911992
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
198919901991
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
198819891990
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
198719881989
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
198619871988
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December
19861987
  • January
  • February
  • March
  • April
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December