Oleg Andreev



Software designer with focus on user experience and security.

You may start with my selection of articles on Bitcoin.

Переводы некоторых статей на русский.



Product architect at Chain.

Author of Gitbox version control app.

Author of CoreBitcoin, a Bitcoin toolkit for Objective-C.

Author of BTCRuby, a Bitcoin toolkit for Ruby.

Former lead dev of FunGolf GPS, the best golfer's personal assistant.



I am happy to give you an interview or provide you with a consultation.
I am very interested in innovative ways to secure property and personal interactions: all the way from cryptography to user interfaces. I am not interested in trading, mining or building exchanges.

This blog enlightens people thanks to your generous donations: 1TipsuQ7CSqfQsjA9KU5jarSB1AnrVLLo

Smalltalk methods

“There are two basic type of method: ones that return an object other than self, and ones that cause an effect. […]
As a general philosophy, it’s better to try and make your methods one type or the other. Try to avoid methods that both do something and return a meaningful object. Sometimes it will be unavoidable, but less often than you might expect.”

Smalltalk by Example: Chapter 3

Don’t tell, don’t ask

While searching for “tell, don’t ask” I have got an interesting wikipedia article.

Is there a CS book teaching us how to write big complex programs?

The biggest advantage of dynamic languages

The biggest advantage of dynamic languages is interactivity. With dynamic language you can open any part of the running system, change something and see how it behaves under these particular conditions, immediately. This dramatically improves design cycles, completely eliminates compile lags and helps to debug efficiently.

Smalltalk/Self guys got it more than 30 years ago.

It is pity to see how current Ruby/Python/JavaScript/etc. frameworks are less interactive than C++/Java within some modern IDE (like Visual Studio).

If the dynamic VM is a move forward, then next step are highly interactive tools. Everything else is just the same old story.

See also real life benefits of dynamic languages at stackoverflow.

Io suggestion

Based on hash table vs. message-receivers and activatable slot, not value.

1. Every slot is activated on direct access. Non-activatable slot access raises exception.

2. x := y creates getter method(getSlot(“_x”)) and setter method(v, setSlot(“_x”, v); v).

3. x = y is parsed as x=(y) (i.e. message x= with argument y).

4. No ::=operator.

5. Method definition: obj setSlot(“add”, method(x, self + x))

5.1. Method definition macro: obj def add(x, self + x) (could be implemented in Io itself)

Pros:

- cleaner setters and hooks for setters;
- smaller syntax;
- uniform message dispatch: each message is processed by a method;
- safety: no need to use getSlot(“x”) for method arguments when activatable value could be passed (relevant to any abstract algorithms).

Cons:

- performance hit since local variable access should perform double hash table lookup; this could be optimized by storing hidden variables (_x) in a plain array.

What do you think?

cee-ass-ass rule (before I forget)

1. Use divs with float:left/position:absolute and negative margins ONLY for the global page layout.

2. For inner modular things like “thumbnail with centered image and centered caption” NEVER EVER use layout tricks mentioned above. Always make sure the module does not require specific outer tags and styles. This is generally possible using tables.

Reasoning: when the smart object is inserted into unprepared environment (div or table) it is nearly impossible to put it into correct position since it has lost its height which should stretch outer container.

Really getting there from here

This is an important addition to the previous article.

Yesterday I have stated that every incremental development process suffers from increasing module coupling by definition. Smaller steps give you flexibility to turn around a current point in the development process, but not to jump out of it.

In previous article I have completely missed the first statement and started talking about “refactoring 2.0”. In fact, when you have reached first N lines of code in your project you should start a new feature from scratch (literally: create new folder, git init, etc.) This action could be considered as a small jump out of the current environment towards the latest requirements.

When you start building something side by side with the existing environment, you are forced to define some minimal API for the existing code to communicate with the new feature. This could be object-oriented API, config file or network protocol. Maybe you would need to refactor existing code in order to provide such API. In result you would produce two less coupled modules which will give you more flexibility as project gets bigger.

An observation: smaller module is easier to fit into a reasonable API. Complexity grows exponentially in respect to code size.

Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. Brian Kernighan (via nelix)

Reasonable rants against functional programming

1. Lisp and Smalltalk

2. Immutable state is something I don’t care for, so it worries me that referring to map, filter, etc as “functional programming” may give people the impression that they have to swallow this immutable state business in order to use these things.
The Danger of Equating Map and Filter with Functional Programming

3. Objects vs. Closures

Getting there from here

Inspired by You Can’t Get There From Here c2.com article

Every incremental development process suffers from increasing module coupling by definition. Smaller steps give you flexibility to turn around a current point in a development process, but not to jump out of it. With incremental process you are reaching local optimum: the best solution for the problem you are not solving today. But this is not the real issue (at least, you can sell it to someone else). The issue is that you can’t move incrementally from the local optimum due to high coupling. The only way out is to take independent components which are suitable for the new task, jump out of the current point and set up new process based on these components. Efficiency of this jump is measured in total relevance of all these components.

In other words, we need some insurance that some critical amount of investment (1 month, $100K etc.) is not thrown away as a whole thing. To achieve this we should keep the work splitted into small distinct pieces, each of the acceptably low cost.

It is usually recommended to refactor the code in order to extract abstract entities and generalize their API. However, it looks like a stupid game in the same playground: a single project directory tree with 1000 files in it.

Lets take a look at search tree balancing principle: each node should have some optimal number of children. If it has too many children, we have to evaluate linear search in the node. If it has too few, we have to evaluate linear search through the linked list instead of a tree.

Our asset is the code. The efficient evaluation of the code requires to keep it in a good shape. This could mean the following:
- N lines of code per method
- M public methods per class/module (+ M private)
- F modules/files per folder
- L levels of folders per library/dependency
- D libraries/dependency per product/another library.

Each figure is average. You can have 10*N lines method as long as there are ten N/10 line methods. The ultimate goal is to have maximum L*F*M*N lines of code per program (as well as M*N lines per class).

Figures could be something like that: N=7, M=7, F=17, L=3, D=7.

The idea is to limit the amount of code you work with. If you do so you would be pushed to extract least coupled parts out of the project, therefore making them more valuable individually and giving more focus to the essentials.

This implies slightly different mindset comparing to traditional refactoring. You do not look for a way to restructure the program just for making it cleaner: you look for a way to keep as little code as possible by extracting least relevant code into separate external modules.

Python paradox economics

Another example of the inefficiency of large organizations. Individuals have little to gain in successfull projects (the company won’t make them rich), but much to lose in unsuccessful ones (they could loose their job). So the rational decision is to avoid risk, as it is not balanced by return.”

See also Python paradox