Oleg Andreev

Month
Filter by post type
All posts

Text
Photo
Quote
Link
Chat
Audio
Video
Ask

November 2008

Church encoding in Pythonjtauber.com
Nov 27, 2008
#python #church #fp
Jim Weirich, Chris Nelson code review (mp4)rubyconf2008.confreaks.com

ROTFL!

Nov 27, 2008
#ruby #rails #tdd
DSSV: Double Space Separated Values file format

We already know CSV and TSV: comma-separated- and tab-separated- table formats. CSV looks ugly in human-readable files, TSV suffers from the invisible whitespaces and editor-dependent formatting.

I suggest another format for human-readable files: a list of records with fields separated with two or more spaces.

This helps to format the file with spaces only and avoid bloating file with quotes (and quote escape sequences). Text looks nice and light without unnecessary commas, quotes, backslashes and invisible tabs.

The only rule is:

1. Lines are separated by [\r\n]+
2. Fields are separated by \s\s+

The parser is obvious.

Actually, this format is already used in a variety of config files in *nix systems. Most noticeable example is /etc/fstab.

PS. Never use tab character where possible!

Nov 22, 2008
#tsv #csv #dssv #design #ui
MVC review: how to write code and tests

Some web2.0 guys might not understand quite well what each part of the “ehm-veh-ceh” pattern should and should not do. They should forget about “fat model and thin controller” misconcept. Today we try to help them. (Code should be light in either case.)

First of all, a simple example about “why it matters”:

A music player contains two volume controls and a sound stream. One control is a slider, another one is a “mute” button. Sound stream has an API with “volume”, “bass”, “track number” properties. If you try to modify sound stream directy within button and slider event callbacks, you will face a problem of UI consistency: when mute button is clicked, slider should be disabled or slide down. Ad hoc attempt is to bloat your callbacks with bunch of if-then-else branches checking all the possible cases in the whole UI in each callback!
A better way is to setup a single controller for all the volume controls with two actions: “triggerMute” and “setVolume(level)”. Then, subscribe each button to a volume property of the sound model, so that slider moves a handle according to the current volume level and mute button looks “unpressed” when the level is > 0. The final step is a controller which simply sets the volume level or triggers it. The only visible if-then-else branch here is the triggerMute method which should check the current volume level before changing it. However, this is an application-specific behavior which is out of scope of MVC pattern.

Generally speaking, your application is about “entities”. Given that:

1. Models are about state of entities. They describe consistent state and referential integrity within the whole system. Model must guarantee that any transition will result into consistent state. Model defines validations and constraints, but doesn’t define how transitions are performed (e.g. doesn’t check permissions). In case of database record, it should allow to change any values in any way, but ensures the consistency of the state just before transaction is committed. Perfect Model does not have “action” methods, but reader/writer accessors only.
When you write tests for a model (you write them, don’t you?) you should not describe an “operational process” with a model, but rather check that any possible update yields a valid state or appropriate errors are raised.

2. Controllers, on the other hand, are about actions. Controller does not bother about consistency of state (it may be stateless) but it specifies the control flow. That is, checks permissions, creates, deletes and moves entities around.
In a test for a controller you should describe initial state of the system, perform an action and then check the resulting state.

3. Views are about representation of the entities. View does not modify the entity, but it accesses its data, observes changes made to a model and generates events for a controller. When you test a view, you should define a set of entities (the input) and check their representation (the output).

The most simple and powerful MVC picture looks like that:

M -> V
V -> C
C -> M

View observes the state (M.) and updates itself when state is changed.
Controller observes the view and performs appropriate actions when some controls are triggered.

Bonus track. How to write perfect tests for a music player “volume feature”?

1. Model test verifies that volume level could not be below zero or over 9000.

2. Controller test checks several values for the “setVolume” method and two cases for the “triggerMute” method: with level = 0 and level = 1. Before the test, volume level is set to some value and after the action it is checked.

3. View test should check that the slider and the button generate events for the controller and observe events generated by the model.

Nov 20, 2008
#mvc #oop #ui #events #patterns
“детей еби жестче за хуевый код и тесты”—сказал мне Миша
Nov 13, 2008
Developer's independence

Goddamn, developer MUST be independent. Switch on your brain, please. RTFM.

Nov 13, 2008
Patterns of software development: "Coincidence pattern"

Software source code is not a big truck a static thing. It evolves over time. Some piece of code being repeated in several places doesn’t always mean that it should be DRYed right away. There’s always such thing as coincidence. When you are putting some functionality into reusable module it should have a meaning applied to the business logic, not just “repeated lines of code”.

What’s the big problem with the “premature drying”? When compiler looks at the code, it just executes it. It doesn’t really matter how deep in the classes and functions some expression is located. It is just a matter of performance.

But when developer looks at the code, he constructs abstractions and loads them into his brain. Developer speaks abstractions language, not expressions. When I see some method/module being used in several places, I understand that as a kind of relationship existing between those places of the system. I see something in common. This idea influences further understanding and I’d better not to be wrong at some point.

Rule of thumb: don’t try to save less than 273 bytes of code if it may lead to confusion and create more abstractions or rules to be remembered.

Nov 6, 20081 note
#refactoring #dry #rule #code #patterns
Mass assignment

1. Controller is not aware of our business logic and that’s a good thing.

 Project.new(params[:project])

2. Initializing objects using hashes is convenient. Also, DataMapper uses it internally to initialize associations.

 Project.new(:any => :param, :goes => :here)

3. Some params are special and are not allowed to be manipulated by user.

 Project.new(params[:project].reject{|k,v| 
    k.to_s =~ /^id|owner(_id)?$/ 
 })

4. Some params are not so special, but are accessible by specific user groups.

 @project.update_attributes(params[:project].reject{|k,v| 
    k.to_s =~ /^owner(_id)?$/ && 
    @project.owner != current_person  
 })

5. While models maintain consistent state of the system (key uniqueness, correct data formats and relationships), controllers maintain control flow (hence the name) along with authentication and authorization.

6. Therefore, currently used mass assignment protection implementations do not solve the problem. attr_accessible/attr_protected methods in ActiveRecord get in your way. A plugin for DataMapper I wrote yesterday also doesn’t help.

7. The right solution is a mix-in module for controllers with before filters, which should safely instantiate all necessary models.

Nov 5, 20081 note
#ruby #activerecord #datamapper #mvc #design #code
Ruby local variable semantics

0. When ruby parser encounters assignment statement on some term looking like a local variable (a = 1, b ||= 2 etc.), it creates such variable. That’s why it knows later that “a” is a local variable, not a method call.

1. Sometimes this leads to a confusion:

def x;  :x; end

def y
  x = 42 if false # assignment is not executed
  x
end

y #=> nil (not :x as someone could predict)

2. But sometimes it helps a lot (merb):
# partial will have a local variable named "some_option"
partial(template, object, :some_option => 1)

# in this case there won't be a local variable "some_option"
partial(template, object)
Inside the partial you cannot simply write if some_option because it will raise NameError in case :some_option was not passed into the partial. However if (some_option ||= nil) works in either case.

Note: some_option || nil won’t work because it is not an assignment statement.
Nov 4, 2008
#merb #ruby #semantics #metaprogramming
JavaScript Y combinatorw3future.com
var Y=function(g){return function(f){return f(f)}(function(f){
  return g(function(){return f(f).apply(null, arguments)})})}
var factorial=Y(function(h){return function(n){return ( n 
Nov 4, 2008
#javascript #events
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