Create a search…then speed it up by a factor of 50!

One great way to implement a basic search is to put all your data fields into one big array and then perform the search on this one field. Let’s say, you’ve got a Customer model. Open up customer.rb (in app/models/) and write this few lines of code:

class Blueprint < ActiveRecord::Base
 scope :search, ->(search){ where('keywords LIKE ?', "%#{search.downcase}%") }

 before_save :set_keywords

 def set_keywords
    self.keywords = [name, email, birthdate, etc.].map(&:downcase).join(' ')

To pick only the searched items we’re creating a scope to which we’re passing the search argument. You can add a function, which will turn all separate fields into one big keywords array.

Now, open up your Controller (CustomersController.rb)

class CustomersController < ApplicationController
  @customers =[:search])

If desired, you can add some validation for cases if no search parameter is provided.

This approach won’t yield you amazon like results, but can bring one pretty far.

Step up the game

If you want to make one little step further and do not want to bother with „heavy industry“ tools like ElasticSearch, then you can utilize PostgreSQL’s awesome built in indexing features. This approach requires a bit more setup, than the first one, but once you follow those steps, it will appear straight forward.

The main goal is to write our custom SQL query. In the end what we want to achieve is something like this:

  lower(first_name) LIKE 'bob%' OR
  lower(last_name)  LIKE 'bob%' OR
  lower(email)      LIKE ''
  email = '' DESC,
  last_name ASC

Using rails syntax this would mean we need a query like this:

Customer.where("lower(first_name) LIKE :first_name OR " +
  "lower(last_name) LIKE :last_name OR " +
  "lower(email) = :email", {
    first_name: "bob%",
    last_name:  "bob%",
    email: ""
}).order("email = '' desc, last_name asc")

To create this query and keep things clean I’m using an extra class (models/customer_search_term.rb):

class CustomerSearchTerm
  attr_reader :where_clause, :where_args, :order
  def initialize(search_term)
    search_term - search_term.downcase
    @where_clause = ""
    @where_args = {}
    if search_term =~ /@/

#Following code goes there

Now we need this helper function, „build_for_name_search“ (I’ll omit the first one for now).

def build_for_name_search(search_term)
	@where_clause << case_insensitive_search(:first_name)
	@where_args[:first_name] = starts_with(search_term)

	@where_clause << " OR #{case_insensitive_search(:last_name)}"
	@where_args[:last_name] = starts_with(search_term)

	@order = "last_name asc"

def starts_with(search_term)
	search_term + "%"

def case_insensitive_search(field_name)
	"lower(#{field_name}) like :#{field_name}"

This function does nothing else rather than building the string for our SQL query. You can verify it by examining the variables – @where_clause is a string, while @where_args is a hash.

Finally, let’s build our controller:

class CustomersController < ApplicationController
	def index
		if params[:keywords].present?
			@keywords = params[:keywords]
			customer_search_term =
			@customers = Customer.where(
			@customers = []

We’re almost there. This search works, but it’s still a bit slow (see below for speed results).

Now we need to create custom indexes on those tables. We will stick to old up and down migration methods, since rails won’t understand our custom SQL migration if we’d stick to „change“.

class AddLowerIndexesToCustomers < ActiveRecord::Migration
  def up
  	execute %{
  			customers (lower(last_name) varchar_pattern_ops)

  	execute %{
  			customers (lower(first_name) varchar_pattern_ops)

  	execute %{
  			customers (lower(email))

  def down
  	remove_index :customers, name: 'customers_lower_last_name'
  	remove_index :customers, name: 'customers_lower_first_name'
  	remove_index :customers, name: 'customers_lower_email'

It’s important to use „varchar_pattern_ops“, since we are not using an exact match, but instead using a like operator. Now, if we fire up rails dbconsole and perform EXPLAIN ANALYZE on both methods, we can see the difference.Ama

This was the original result:

Started GET "/customers?utf8=%E2%9C%93&" for ::1 at 2017-01-04 22:19:21 +0300
Processing by CustomersController#index as HTML
  Parameters: {"utf8"=>"✓", "keywords"=>"", "commit"=>"Find Customers"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
  Customer Load (561.3ms)  SELECT "customers".* FROM "customers" WHERE (lower(first_name) like 'andres%' OR lower(last_name) like 'andres%' OR lower(email) like '')  ORDER BY lower(email) = '' desc, last_name asc
  Rendered customers/index.html.haml within layouts/application (572.4ms)
Completed 200 OK in 591ms (Views: 27.8ms | ActiveRecord: 561.6ms)

After spicing things up:

Started GET "/customers?utf8=%E2%9C%93&" for ::1 at 2017-01-04 22:40:59 +0300
Processing by CustomersController#index as HTML
  Parameters: {"utf8"=>"✓", "keywords"=>"", "commit"=>"Find Customers"}
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
  Customer Load (2.1ms)  SELECT "customers".* FROM "customers" WHERE (lower(first_name) like 'andres%' OR lower(last_name) like 'andres%' OR lower(email) like '')  ORDER BY lower(email) = '' desc, last_name asc
  Rendered customers/index.html.haml within layouts/application (12.7ms)
Completed 200 OK in 32ms (Views: 28.3ms | ActiveRecord: 2.3ms)

This is an increase by a factor of 243! – the new source for EVE Online productioneers

Greetings, capsuleers!

Few days ago I launched my long time dreamed project – ( This services is intended to be a lightweight alternative to updating your excel sheets daily with current prices (most likely you will get them from Via the API I fetch the prices on requested blueprints, calculate for you the cheapest material prices and suggest where you can sell the end product most expensive.

Settings and assumptions as of today:

  • Areas considered for calculation are all solar systems within 5 jumps around the five main trade hubs (which currently are – Jita, Amarr, Rens, Dodixie, Hek) and which are high sec
  • All skills are lvl 5 (which you probably should have if you considering make money with industry)
  • No fees and taxes are calculated (if they are hindering you to make profit you are producing the wrong thing)

The service is in it’s early stage, so be prepared to encounter some changes in near future. What is planned:

  • Having at least a few options available in an „expert“ menu
  • News section
  • Implement user accounts where user can save their blueprints, thus, having a faster access to their favourite blueprints
  • Having a history saved for each blueprint.
  • A suggestions feature, where users can suggest new things and other users can vote on them.
  • Making market predictions based on Monte-Carlo-Simulation or Expected Shortfall methods.

Properly create and restore your development postgreSQL on production

So maybe you are like me, who is parsing a lot of static data into a development database, make an app around this data and then you don’t want to have an empty database on production, but instead you want to have a full copy of your development database.

After spending a few hours trying to make it work, there is one solution, that yielded exactly 0 errors (yay!)

On your local machine (in the shell, wherever you currently are) :

pg_dump --no-owner your_db_develoment > backup.bak

Then put it in some safe place on your remote machine:

scp backup.bak deploy@

Make a backup of your production database for safety sake (on your production server, of course)

pg_dump --no-owner your_db_production > /home/backups/04-03-2016/backup.bak

If there is no production database yet on the server, proceed with creating it, elsewise you might need (if the app has users) to cut the current sessions, so check these out:


Ok, now we have no database on production machine at all. Let’s create new production database:

postgres=# CREATE DATABASE database_production;

postgres=# CREATE USER production_db_user WITH password 'qwerty';

postgres=# GRANT ALL privileges ON DATABASE database_production TO production_db_user;

Make sure to populate the password with the same password, as set up in database.yml for production user.

That’s it! No need to change the owner. Now let’s restore the backup file:

sudo psql -d mydb_production -U production_user < /home/deploy/restore/backup.bak;

Password for user production_user: 
ERROR:  must be owner of extension plpgsql
COPY 14964
(1 row)

COPY 3151
(1 row)

COPY 28011
(1 row)


As of now I have no issues regarding the one error above.

Sneak peak – Team Geek

When communicating with other people (not only with your colleagues), remember the golden rules which I picked up reading this fairly amazing book (a complete review will follow later) :

  • Ensure that your email can be read in 10 seconds.
  • Your explanations should be covered by three paragraphs at most
  • You should end with a call to action

It is amazing how this simple rule is not followed in most cases of everyday non-verbal conversation.

Rails eShop – my first big project using Ruby on Rails

[readolog_dropcap ]H[/readolog_dropcap]appy new Rails year, fellow riders!


I finished my very first „serious“ project – yay! It looks and behaves like a rails eShop (you can find link further down below). Before I go into technical details some intro – this website was created for friends of mine and although it was kind of experimental for me (first real app), it turned out to be quite decent as one might say so.

As with every customer-oriented project, there was a lot of JavaScript involved, which is by far not my strongest language. It started calm and nicely with pure ruby on rails, I could use a lot of stuff I learned from this book – Agile Web Development With Rails. But then… as more and more wished appeared I realized that there is no way around some front-end development.

Enough smalltalk, let’s get straight to the data:

  • Bootstrap Theme used – „Minimal
  • Notable gems: figaro (managing global variables), devise (users), carrierwave (images uploads), sendgrid (for sending any kinds of mails)
  • Database: postgresql (I think it’s pretty a must-have for shops because of hstore – which, as far as I understand makes postgres almost non-relational, because hstore columns allow to store hash/value pairs)
  • Deployment: capistrano, puma, nginx (you can check out my article about deployment here)
  • Other features: protected admin namespace

[readolog_dropcap ]M[/readolog_dropcap]ost notable code


JavaScript – a calculator for end value of a product based on amount, delivery method and size (plus additional services, which are to be differentiated between one for each product and one for a full order). There is some hard coded stuff and of course this piece of code might not be the state of the art, however it works pretty well.

$(document).ready ->

    if $('a.size_input').length != 0

jQuery ->
    $('li a').click (event) ->
        # event.preventDefault()

    $('form').on 'click', '.add_fields', (event) ->
    	time = new Date().getTime()
    	regexp = new RegExp($(this).data('id'), 'g')
    	$(this).before($(this).data('fields').replace(regexp, time))

    get_multiplier = ->
        amount = $('#amount').val()
        multiplier = 1.5
        multiplier = switch
            when amount <= 99 then multiplier = 1.5
            when amount >= 100 and amount < 300 then multiplier = 1.4
            when amount >= 300 and amount < 500 then multiplier = 1.3
            when amount >= 500 and amount < 1000 then multiplier = 1.25
            when amount >= 1000 and amount < 3000 then multiplier = 1.23
            when amount >= 3000 and amount < 7000 then multiplier = 1.2
        return multiplier

    get_delivery = ->
        delivery = $('#delivery').val()
        return parseFloat(delivery).toFixed(2)

    get_size = ->
        # in this method we either select the price value based on the flash
        # drive size, or, if it has a basic price, just simply the basic price
        # from the hidden #basicprice id

        selected_size = $('input[name=volume]:checked').val()
        if (selected_size == undefined)
            return parseFloat($('#basicprice')[0].innerText)
            array = selected_size.split(",")[1].replace(']','')
            return parseFloat(array).toFixed(2)

    get_all_addservices = ->
        # This method delivers all checked addservice price
        # so we can first substract it before applying any multiplications
        addservices = new Array()
        addservicesParty = new Array()

        console.log('inside get all addservices:')
        checkboxes = document.getElementsByName("addservices[]")
        for checkbox in checkboxes

            addserviceprice_splitted = (checkbox.value).split(" ")
            # console.log(addserviceprice_splitted[2])
            # Here we need to check if the 'apply to whole party is true or false'
            party = addserviceprice_splitted[2]

            addserviceprice = parseFloat(addserviceprice_splitted[1]).toFixed(2)
            if checkbox.checked
                parsedPrice = parseFloat(addserviceprice)

                if party == 'true'

        if addservices.length > 0
            sum = addservices.reduce((a,b) => a+b)
            sum = 0

        if addservicesParty.length > 0
            sumParty = addservicesParty.reduce((a,b) => a+b)
            sumParty = 0

        console.log('Addservices combined: ' + addservices + '| Addservice to whole party: '+ addservicesParty)
        return [parseFloat(sum), parseFloat(sumParty)]

    recalculate = ->
        # This function recalculates the price
        base = get_size()
        deliveryCoefficient = get_delivery()
        amountCoefficient = get_multiplier()
        addservices = get_all_addservices()

        addserviceOne = addservices[0]
        addserviceParty = addservices[1]

        amount = $('#amount').val()

        console.log('base - ' + base + '| delivery - ' + deliveryCoefficient + ' | add service sum - ' + addservices + ' | amount coefficient - ' + amountCoefficient)

        endPriceOne = (base*deliveryCoefficient*amountCoefficient) + addserviceOne
        endPriceParty = (base * deliveryCoefficient * amountCoefficient) * amount
        endPriceAll = endPriceOne * amount + addserviceParty
        endPriceServices = (addserviceOne * amount) + addserviceParty


    $('.size_input').click (event) ->
    $('.addservice_checkbox').change (event) ->

    $('#amount').on('input', (event) ->

    $('#delivery').change (event) ->

    $("#thediv").click (event) ->

    $('#load_more_btn').click (event) ->

Here we have some fancy helper methods which I grabbed from Ryan Bates screencasts. They allow you to add fields on the go:

module ApplicationHelper

	def hidden_div_if(condition, attributes = {}, &block)
		if condition
			attributes["style"] = "display: none"
		content_tag('div', attributes, &block)

	def link_to_add_fields(name, f, association)
		new_object = f.object.send(association)
		id = new_object.object_id
		fields = f.fields_for(association, new_object, child_index: id) do |builder|
			render(association.to_s.singularize + "_fields", f: builder)
		link_to(name, '#', class: 'add_fields', data: {id: id, fields: fields.gsub("\n", "")})

[readolog_dropcap ]L[/readolog_dropcap]ast, but not least


we have of course a fully functional rails eShop with a working cart, order placement, sending confirmation letters to customers and admins, an administration panel for managing products etc. etc.

Unfortunately the owners decided to put this page on ice, therefore it’s unlikely that you will receive some flash drives. However you can check the page out all by yourself –


The Software Development Edge – Book Review – Part III/III

Finally I gathered all the strength required to finish this review. It’s a little bit tougher than back in the school days, however I hope it might serve some educational purpose.

As explained in the last post, this review part will not continue the previous path, but summarize the whole book (in a shorter way). You can regard this as a kind „best of“.

Core idea – Politics

[readolog_blockquote ]“Developing software is such a unique and complicated process, I can’t make an estimation how long it will take and I won’t take the responsibility for my due dates“ – this is utter bullshit. Software development is just as unique as any other professional field (just ask your friends). If someone refuses to take over responsibility it’s is clearly not because he/she is such a genius.[/readolog_blockquote]

Core idea – Crisis

[readolog_blockquote ]Act – that’s the main point. Regardless if you’re a hired crisis manager or were just moved to another project which is deep in the shit, your main goal now is acting. It will stink for a while, so don’t bother with keeping good relationships (with customers, other employees, anyone…).[/readolog_blockquote]

Core idea – Project

[readolog_blockquote ]Keep your project within the given due date. Do it at any cost – mostly you will be cutting off unnecessary features. However you can’t fit any project in any time frames. Take your time in advance and get an honest opinion from your team members how they estimate the whole project. You really need those honest opinions and people you can trust. If you can’t, it’s time to say goodbye to those.[/readolog_blockquote]

Core idea – Developing

[readolog_blockquote ]It might be some de facto standard right now, but still I see even in my team how things can quickly get out of control if you don’t invest time into concentrated continuous releases, called iterations. Force everyone to deliver something each week. It will require a lot endurance from you, but there is just no other way…[/readolog_blockquote]

I promised to keep it short and simple and here we go. Four core points which should awaken your interest in this book. If you want to intensify the review reading I would recommend you part I and part II, however more than that I would just suggest you go out there and buy this amazing book.

How to write useful technical specs

I might be not that wrong in assuming that a lot of IT people out there encounter same problems regarding tech specs all the time – they become obsolete sooner than they are written. Mostly created to show the client – hey, we’re doing stuff here, here is the result, 100 pages of pure informational power. However, the result is often the same – after one glance, each team member will soon forget that this spec ever existed.

So how make specs more useful? In this article I won’t show how to formulate your spec, but more how (technically) to manage, that your spec stays up to date.

Use LaTeX

No, not in the bedroom with your girlfriend (on the other side – who am I to judge you?), but the document markup language (according to Wikipedia).

LaTeX is not only cool – writing specs feels almost like writing code – but it allows you to maintain a healthy development process considering your spec.

Problem No. 1

When your specs are starting to get bigger and you add stuff here and there, it is very (VERY!) hard for your team to follow up on changes. Using GIT in combination with LaTeX allows you to commit any changes just if it were code. And GIT markup fantastically highlights all changes that were made. So next time you can just give your team a link to the latest commit to they will see only the new and recent parts.

Problem No. 2

Have you ever tried to create links within a document, say in MS Word? Yeah, you kinda able to do that, but if you add, say, a new point to your numerical list, all your links will get messed up. Regardless to say what happens if you add a whole new chapter at the beginning. LaTeX allows you to define variables, just like any programming language. Just use a simple


where section:intro is just a clear variable meaning that your content is in the section called „intro“.

Problem No. 3

As soon as you try to maintain your MS Word spec you realize how this program is clearly not created to write large documents. Ever tried to create a numerical list, then add a break and continue the list? Then you’ll know how easy it is to screw things up. By being completely controllable there is always an easy solution for almost everything you want to achieve with a LaTeX document.


I mentioned it already in the previous paragraph, but I can’t stress it out enough – your LaTeX spec will really shine bundled with GIT. Not only you have a neat version control (and don’t need to save „project_x_tech_spec.v.1.0.docx“, „project_x_tech_spec.v.1.8.docx“ and so on), an ability to link only your recent changes by sending a commit link, but you also have one place for your always up-to-date end format, because recently github learned how to display pdf-files.

So basically your pdf url stays always the same, something like this:

My setup

Since TeX is permissive free software (to me it sounds a lot like open source), there is a bunch of good free editors (honestly, even notepad will do it). However I felt in love with Texpad – it’s available only for MacOS (and iOS) and makes full usage of your retina display. It costs 25 $ and is available for download at Texpad homepage.

Starting writing documents with TeX may be a bit hard the very first time (on the other hand – what isn’t hard the very first time?), but there are plenty amount of templates out there on the interwebs helping your out to fire your document up. My personal favorite (there are few Russian language related things which you might omit) :

\documentclass[DIV=calc, paper=a4, fontsize=11pt]{scrartcl} % Документ принадлежит классу article, а также будет печататься в 12 пунктов.
\usepackage[utf8x]{inputenc} % Включаем поддержку UTF8
\usepackage[russian]{babel} % Пакет поддержки русского языка
\usepackage{titling} % Allows custom title configuration

%for frames

%For image using

%Numbering subsubsubsections etc

%For code highlightning

%Further enumeration - you might omit that! It can lead to strange numeration!

%For referencing within enumeration lists

%Packages for word-like comment style
%This is really awesome! You can add marks that are highlighted.
%My personal favorite usage is like this: \todo[inline]{some comment goes in there}

%Package for images

%For a nicer reference



%For some math formulas if needed

% Some nice visualization
%\usepackage[svgnames]{xcolor} % Enabling colors by their 'svgnames'
%\renewcommand{\headrulewidth}{0.0pt} % No header rule
%\renewcommand{\footrulewidth}{0.4pt} % Thin footer rule
% End visualization

%smart enumeration

\title{Some title goes in there}



... Here goes your content with \section{} and \subsection{} and everything else...


Happy writing!

The Software Development Edge – Book Review – Part II/IV

Let’s continue where we left last time.


It is important that you are able to explain your software to non-coders. This however involves other techniques than showing code (when abstracting a bit, showing code might be the worst way to explain software).

The other extrema – typically found in „management level“ PowerPoint presentations, showing absolutely nothing useful at all. Avoid it.

Writing code

As a it project manager you should be familiar with the language your team is using. Even if you come from a different language and were a professional coder yourself, it doesn’t always mean that you will know which problems the team using that specific language will encounter.

Since beginning by reading books is quite terrible and boring idea the best way to learn a new language is to write a program that covers a lot of topics (and in turn, this topics could lead to serious problems). You need a standard program.

Standard problem

It should cover:

  • (Console) line in / output
  • Retrieve data entered by user
  • Simple algorithms
  • Long term data storage
  • Standard data structure like linked lists
  • How to deal with exceptions
  • How will the program scale, will it adapt to new requirements

A wonderful solution is provided by the animal game (I’ll cover that on an extra page).

Get out!

Each product has only one goal – to suffice the customer’s demand.

Even the smallest projects tend to grow and expand. If you omit integration process the entropy will finally win.

Convince your superiors to provide you with best people possible for the integration process. Every project needs its „king of deployment“.

Continuous integration and version control are your tools to go – someone messed something up? Just revert his/her commit. You need a build every night with all tests up and running? CI is your friend.

Avoid „we’ll write a script for this problem“ at any cost. Scrips are fragile and are hard to debug. Your road to hell is paved by scripts that got out of control.

While integrating there are only few ways to do things right and a lot more to mess stuff up. Take the integration seriously, invest every possible minute in it.


The two most important thing you’re obliged to do as project manager – keep your project within initial borders and don’t let it die a slow feature-death.

I think everyone knows the basic triangle – volume, resources, time (pick two). Marasco however adds a fourth dimension – quality (nobody will care a year later on if you delayed your project or exceeded budged, only quality will remain).

At this point a small digression – Marasco now translates this thoughts into some mathematical formulas. Although I’m not a fan of stuff like „If we assume normal distribution we can calculate the probability of our project to fail…“ – please don’t do that. If you ask every team member „can we do that project?“ – their answers is your best probable guess, not some distribution. However some conclusions are to be considered:

Like Brooks said – most project fail because of lack of time compared to all remaining reasons combined(!).

You can’t compensate lack of one parameter by the other (in big volumes).

You should adjust parameters equally (you can’t add a ton of quality with just one week development time)

Time estimation

As a project manager it is your duty to create an atmosphere of confidence – nobody should be punished for not being able to give a perfect time estimation. This only leads to defensive mechanisms and developers will often increase the estimation to be on the safe side which in turn is bad, because you can’t rely on this numbers.

What is the main source of all evil project problems? Basically every project manager sees the working time estimation (for the whole project) as a working document, while their superiors see the time plan as a contract. Often it arises two types of time plans – one for the outside world and one for the inner development. This is a little fraud and Marasco recommends using one honest time plan.

What are main reasons for bad planning? First of all – there are almost never known all connections between certain software parts. Just use some simple combinatorics – if there are two parts that needed to be connected, there are only 2! = 2 ways of doing that. If there are three parts we have 3! = 6 ways of combining them. Let me just tell you, that n! increases really fast… You can prevent that by using small iterations, because by forcing to release a working product at the end of an iteration you can reveal hidden dependancies.

Second main reason is that delay may sneak in unnoticed. Brooks said – a delay by a year starts with a delay by one day.

If time estimation was given honestly your usual project delay should be around square root of remaining time. Let’s say you are at time point 0 and your project is estimated by 16 weeks. This means that you will probably finish between 16 and 20 weeks from now on. If you are in week 12, meaning that 4 weeks are remaining (and everything went fine so far), project delay should be around 2 weeks, meaning total development time between 16 and 18 weeks.

If you end up being faster than square root of a given estimate – you have a typical example (and problem) of someone being too defensive. The only right thing to do is to fire those people.

So basically you have following: ideal time estimation = ITE = good.
ITE +1*sqrt(remaining time) = help required.
ITE – 1*sqrt(remaining time) = excellent.
ITE +/- 2*sqrt(remaining time) = both cases very bad

How to achieve honest and objective estimation? Note every estimation (good thing is, nowadays every task tracking software supports such features) then write down each result based on given estimation. This will help you calibrating your project and the work of each individual project member.

Remember – not the result is important but rather its predictability.

Project rhythm

Just like a lot of stuff in our lives, even software projects follow certain rhythm. Compare it to a learning curve – at the beginning development process is slow – you are planning a lot of things, organize them and do research. Then you gain speed – the main process begins. When reaching the end state you might encounter speed decrease because a lot of little problems pile up and now is the time to solve them.

I bet you can confirm it on an intuitive level – projects start heavily, then accelerate and then stick in sort of swamp. Sometimes a feeling arise that you cross the finish line barely walking.

If we translate this into iterations we can encounter that there is negative „force“ at transition points. This is where you as a PM should invest your energy to get the project curve up again.

Some interesting derivative information from that research – about 60% of required knowledge you receive during the first 40% of the project, but at that point only about 25% is effectively done. It lowers the risks (because you are investing time in planing and research), but on the downside you can’t show a real progress. To discuss the importance of the „learning“ with your superiors you should prepare for example a list of risks and how the learning might reduce or even completely remove such risks.

Right now, as I’m finishing the second part I realize that it just takes too long to write such a detailed summarization and, what bothers me even more is that it makes it even harder for my rare visitor to follow such an analysis. Therefore I will switch from now on to shorter, more personal articles.

The Software Development Edge – Book Review – Part I

Hear me, I beg. And say thankya, big-big. This one is going to be a hell of long post, but do not worry, you can browse through the cites really fast and get all the essential data you need. My very short summary – go and buy this book, remember (almost) every page, it will do you some good. The software development edge by Joe Marasco should be your holy book, your guidance in the dark realm of leading teams and developing software.

I counted exactly 170 good ideas, worth remembering. Regarding a total count of 370 pages we have a score 170/370 ~ 0.46, which is amazing! It means almost every second page you’ll encounter contains something useful.

As you might guess in my book summary I’ll have to cover over 185 pages of ideas. Since it would take too long to release a complete overview at once I decided to split it up in four parts, each covering around 100 pages of text. The first one ends exactly at page number 100.

For now, here we go – book’s best points, no cites but rephrases:


Spend a lot of time talking to your developers, get familiar with details and problems.

Worst combination possible – keenness absence and sloppy management. Mostly, it will lead to programs that don’t work and if they do, not very well.

If you happen to be the team leader, do not easily yield to your superior (of course you should listen and give in in most of the times, but not easily, because your superiors may suggest (due to their unknowingness) unreasonable demands.

Your iterative approach to solving problems: observe, listen, empathize, synthesize, testing, write down.
Observe – look around you. What’s happening? Where could be the source of a problem or maybe it’s symptoms?
Listen – after you’ve located the problem, talk to people and listen to their opinion. Talk less, write more.
Empathize – the clear difference is here to „listen“ – while empathizing you not only collect objective data, but also give subjective feedback.
Synthesize – now put all parts together: your objective data while observing and listening, emotional aspects while empathizing, your box of tools for solving problems (should be mostly your experience). The result – a possible approach for the given problem – should be put out to test.
Write down – now you should write down everything that occurs while your approach is doing it’s job. If you don’t do it it will become much harder to convince others to accept your approach. Besides, what’s not written down is soon forgotten.

Doubt everything. Check every partial solution.

In every big project someone, who is on his/her own is a potential danger. However you shouldn’t throw all people in one big basket. Create as little teams as possible with as little members as possible. Four groups three or four members each may be way more productive than an horde of 50 employees.

Sooner or later every leader will have to make choices. If your team members were chosen correctly they will accept your decision because having one is better, than none decision at all. However it doesn’t mean that you are free to come up with any crap idea – you still need to analyze give situation. The only thing to avoid is to be paralyzed.


The mountain top – the end of your project – should always be the main goal. Everything that hinders you and your team on the way up must be cut off.

On the other hand climbing up in real life is just the half of it, you also need to come down. This can be compared with supporting your existing project – a successful one can be completed and then supported over a long period of time.

Why projects fail

Nonrealistic time schedule

Too many team members, team contains a lot of mediocre developers compared to the best ones.

Neverending stories projects lasting so long, that all requirements change multiple times.

Ignore first iterations‘ results. No analyze and change after seeing them.

Lack of clear goal, understandable by everyone

What can lead to success

Small, but smart plan with few details is more effective than plan overloaded with details

Clear your work before requirements change

Correct your movement’s vector (use small iterations) on the fly

Durability – extraordinary peak strength means nothing on the long term

Concentration – your team don’t lose sight of the goal


Don’t hire high skilled people to involve them in trivialities.

Main point of every task should be a client’s problem. Even more important is for your product to generate additional value for your customer (by solving his problems).

Best leaders can project their sense of goal to others – by giving them a good example. Managers make sure that this goal is achieved. Best people out there unit qualities of leaders and managers.

Take care of every small problem in time. Even smallest problems tend to grow massively. This leads to two kinds of bad managers – the „ostrich“ ones, who won’t see the problem and the „lazy“ guys, who will postpone everything until it’s too late. Don’t be one of them, problems don’t disappear magically.

Do not let you lead easily. Always remember – your goal is to solve a problem, achieve some result, not to make you most popular and well-liked guy in the department.

Don’t panic. Seriously. Be solid as rock. Every crisis will be over, your duty is to participate in solving this crisis, not in overreacting. Be an example for everyone else (rock-solid).

Laugh. Even when facing dumbest customer’s demand, better laugh about it, do it, forget it than making drama.

Teams forgive their managers a lot of things, but laziness, incompetence, lack of reward for efforts and lack of humor are not among them.

Trust your instincts – if you are really feeling uncomfortable with something, trust your inner self, most likely you’ll turn our being right (this also means do not hire people who will make you uncomfortable – in exceptional cases it might be worth the risk).

Developing software

Goals are most likely not where they meant to be. Often because at the beginning the technical requirements are not quite clear und well understood.

During the process people will make mistakes.

Your goal is a moving one.

A good manager will always make a lot of little steps rather than few big ones. This allows to shorten the overall distance because after one misstep you haven’t travelled a big distance and after a dozen steps your next one will most likely be close to optimal.

Do not start with easiest problems. By doing so you’re digging your own grave. Your team won’t bother with upcoming possible risks. Even the easiest task will grow big (there is always room for improvement). This leads to scarcity of time for the real challenge and to one further problem – explaining that you need more time doing the most difficult part, covering the biggest risks is much easier to your superiors than begging for more time because your team was wasting it.

Iterative approach forces you to apply all lessons learned from this project (all previous iterations) to all upcoming iterations of the same project.


How to get your team organized with 5$ per month

Some time ago I had a pleasure (no irony intended!) to start working in a company with no established developing process at all. There was no issue tracking, no communication tools, no code hosting…nothing (nothing but a Russian Bitrix system, but it doesn’t count, since it’s awful and nobody was using it). Now I want to share with you one of myriads of possible approaches. As it happens we pay only 5$ per month to make it work.

How to start?

First of all you’ll need a webserver. We decided to pick up the cheapest DigitalOcean droplet which is available for exactly 5$ per month. You can pick Linode or any other server, where you’ll be granted full root access. DigitalOcean comes with a fancy possibility to create a Redmine-Droplet in just 55 seconds, this is just what we did.

Where to host code?

Trust me, even if you have just one developer you better start using version control. Github is the most common service just to do so, however if you can’t afford sharing your code with the community you got to pay for private repositories. A wide known alternative would be Gitlab, which not only allows you to host the service on your own machine, but also doesn’t charge you for creating private repositories if you continue using on-demand version. I didn’t manage it to install Gitlab on our 5$ droplet (maybe I’m just not gifted… maybe it has something to do with recommended RAM size of 2 Gbyte and two unicorn worker units to be able to handle http requests – 5$ droplet got only 512 MB RAM), so we’re using private on-demand repos. However if you manage to install gitlab on your machine the following routine will be much easier, since pulling from Gitlab won’t requre any hooks as it will be on the same machine as Redmine itself.

How to connect them?

You’ll probably don’t want maintaining two systems at a time. This is where so called hooks come in play. You can try and install but for me, although I set up (at least I suppose so) everything correctly, it didn’t work.  What I did instead was following:

  • create an ssh-key on your server, where redmine is hosted (since chances are you won’t be able to copy the key to your clipboard you’ll need to send the file to your local machine first via scp
pbcopy < .ssh/
scp /some/local/directory
(I never know how to connect to my local PC, so instead I connect to remote machine and download the file)
For example - scp root@ /directory_created_for_the_key
  • now comes a tricky thought – since Redmine hooks only its local repos but your local environment is another one, we need a workaround. As depictured below you need to set up your remote origin as gitlab
git remote add origin
then you push using 
git push -u origin master
Gitlab Redmine connection visualization
Gitlab Redmine connection visualization
  • To keep your Redmine repo up-to-date, you’ll need, first of all, to create one (on the Redmine server) – simply git init /home/redmine_projects/project1
  • Create a cronjob – nano /etc/cron.d/sync_repos
  • Repeat the line for each repository (app should be the owner of the repository. In our case it is „root“)
    */5 * * * * app cd /path/to/project.git && git fetch origin && git reset --soft refs/remotes/origin/master > /dev/null
  • Wooosh! You’re done! Now every push will be visible just 5 minutes thereafter in your Redmine repo-tab.
Now your repo on the server where redmine is installed is always up-to-date (with a 5 minute delay).
Now your repo on the server where redmine is installed is always up-to-date (with a 5 minute delay).