Showing posts with label Baby Steps. Show all posts
Showing posts with label Baby Steps. Show all posts

Friday, 2 May 2014

Watch 'Crazy House', on Friday, after 3 pm, at your work.

If you are lucky, while working on an open space, sometimes, you may see people running back and forth, impinging each other and behaving exactly like headless chickens - especially after 3 pm on Friday ;) The reason why you may see that somewhat peculiar picture is because of either somebody's birthday (i.e. cookies and doughnuts) or production issue ;) Check your mailbox and if there is no email about doughnuts, it has to be an issue on prod!


Usually, managers refrain from communicating a problem to business, before getting some initial knowledge about it. However, do not be mislead by lack of email. That state would not last long. That is actually the time, when managers start to create an Asterix and Obelix 'Crazy House' cartoon atmosphere, harass developers, L3 or any other support team. Of course, they think they do their best to behave in a calm and professional way, but subconsciously they do what all people do, when they are jeopardized - they are clustering into harassment groups behind the back of (un)lucky developer, creating totally unnecessary pressure. 

Then, there is a time for usual questions cannonade: where are we, what we know, what is the risk, what is happening, what are our options etc. You may have an ironic answer for all of them, but you must keep a poker face.



In fact, calmness is your bless. The more clam and methodic your approach would be, the sooner you would be at your home sipping whisky. So calm down and follow below steps:
  1. Ask for a little bit of context and clarification what they think is all that fuss about.
  2. Do not easily believe what 'headless chickens' are saying ;) Check it yourself. If they knew what is going on, they would not harass you ;) Simply ask for evidence based on which they raised an alert. It might be a monitoring screen shoot, DB query, logs, whatever. You may see something, they may have skipped. Also, it is pretty common that people misinterpret what they see and hit 'panic alarm' straight away. It happens, you must live with that.
    You may also ask a couple of context enriching questions like 'who said that' and 'based on what premises you thing so'.
  3. If you really can smell the issue, do an initial investigation and try to estimate:
    - impact
    - risk
    - also it would be marvelous, if you could apply some trends checking here.
    If possible, check whether same or similar situation was happening in the past. Perhaps, it is a regular behaviour.
  4. If there was something similar happening in the past, try to dig out the knowledge about that issue and its remediation. JIRA ticket, conversation with other peers in the project, basically anybody or anything might be helpful.
  5. If not, then it is a genuine issue, which has to be investigated.
  6. If you finally come across the solution and it involves a fix on prod, try to mitigate its risk, by doing the smallest possible change. 
    Remember: small change = small impact (according to stable system definition).
    Assess minimal, optimal and maximal downtime of the system vs. you SLAs. Communicate it clearly to your business stakeholders, prod services and managers.
    Also do not let them suggest solution, unless it has reasonable base.
  7. Test your solution on prod like environment (including starting and stopping your app) and write full sequence of steps. Do not let anybody add/change/remove any of steps, before agreeing it with devs, prod services and testing them properly.
    It's better to have a broken system, where you know what is going on, rather than possibly fixed one, where nobody is entirely sure, if and how it's gonna work.





Monday, 10 December 2012

Code Retreat in ThoughtWorks 2012

This time I was in taking a part in Code Retreat organized by London branch of ThoughtWorks and it was awesome !!



I decided to spent half of a day writing code in languages other than Java. I have chosen Groovy, Ruby and C#. I have to say that all sessions went very well. 
Okay, so let me describe them briefly: 

#session 1: Groovy with no constraints - just a warm up in a language similar to Java.


#session 2: Java and baby steps - this one was very good. The quite nice and neat design was emerging from the code driven by our tests.


#session 3: Ruby and no more than 4 lines of code per method - actually 4 lines of code per method wasn't hard to achieve in Ruby. To be fairly honest, the longest method we had, had literally 2 lines. What's more, Ruby guy, I was pairing with, has shown me some magic in Vim. I thought I knew Vim quite good, however it appeared I am a barely novice :P


#session 4: Java and immutable objects - this was actually quite interesting one, as well. Immutable objects were affecting our design in a way we did not expect, at the very beginning. 


#session 5: Java and no primitives - again another interesting design emerged.


#session 6: C# and tell don't ask (our choice) - that was actually quite a challenge to use only procedures.


All in all, it was very educational, eyes opening and enlightening day. Although there were couple of tricks I learned, I think the most valuable one is related to the way of coping & pasting code. If you really need to do it, do it as below:

- copy & paste the code
- use question marks to denote parts of code you have to amend
- replace question marks with valid code starting from the top

Just to make things clear, let's have a look on a below example:


"Any live cell with fewer than two live neighbours dies, as if caused by under-population."

@Test
public void liveCellWithFewerThanTwoLiveNeighboursDies() {
	int oneNeighbour = 1;
	Cell liveCell = new Cell(ALIVE, oneNeighbour);

	liveCell.tick();

	assertThat(liveCell.getState(), is(equalTo(DEAD)));
}

And here you decided to copy above test in order to tweak it slightly, so that you can get another valid test.

"Any live cell with more than three live neighbours dies, as if by overcrowding."
@Test
public void liveCellWith???NeighboursDies() {
	int ???Neighbour??? = ???;
	Cell liveCell = new Cell(ALIVE, ???Neighbour???);

	liveCell.tick();

	assertThat(liveCell.getState(), is(equalTo(DEAD)));
}

And here is the result:

@Test
public void liveCellWithMoreThanThreeLiveNeighboursDies() {
	int fiveNeighbours = 5;
	Cell liveCell = new Cell(ALIVE, fiveNeighbours);

	liveCell.tick();

	assertThat(liveCell.getState(), is(equalTo(DEAD)));
}

As simple as that, but helps you to avoid silly errors.

Wednesday, 12 September 2012

Early and continuous customer's satisfaction in cyberspace


Let's consider first agile manifesto principle, i.e.: 
"Our highest priority is to satisfy the customer through early and continuous delivery of valuable software."

What it basically says is that there is nothing more important for us, than satisfying our business client through:
  • early delivery
  • continuous delivery
  • delivery of valuable software

Ideally, we ought to start to deliver something valuable for our customer from the very first day, when the project starts. Apart from that we have to remember about delivering these valuable bits constantly.
Hmm ... one may say, in reality, it is quite hard to commence delivering valuable software from the beginning of the project. 
To my mind, an important question seems to be: what is the definition of valuable software from client's perspective? The thing that only matters for business is something that adds value for them. They are 100% right, however in my humble opinion, majority of business people have slightly twisted perception of that definition. In other words, they seem to consider value in places, which directly maps to money. Whereas, a deeper look from risk management angle reveals business value in operational readiness or continuity of deliveries. This also means money, but this time not direct one. The root cause might be lack of risk management skills and not being able to see the clear, bigger picture of what is going on. They seem not to appreciate value hidden in infrastructure almost at all. In contrary, in any army, especially during the war, infrastructure like robust roads and railways or fast and reliable communication channels etc. are fundamental factors. The Second World War proved that rail and roads might be a key to transfer military units between places in few hours. 
Infrastructure, especially CI infrastructure, is not a direct business value itself. Although in IT it is something invisible (all in all everything is a software), the quality of it is a clue and creates a reliable scaffold, where business values can be spread. For instance painters always prime their canvas before painting. They do it in a fairly detailed and decent way, as they know it is a "scaffold for their vision". Infrastructure in IT pays dividend when the project lasts and even after that when it operates. So the question remais: what is a business value? Is infrastructure an added value for business? Is being operational BAU 24/7 a fair point? Aren't these two adjectives (early and continuous) a deliberate game of words in agile's first principle? Apparently contradictory, but in fact complementary statements: early and continuous delivery. In economy, they tend to say the the best business is the one, which is operating all the time. Wait a second, isn't it what we just said that infrastructure is something allowing business to be run and produce value 24/7? Yes that is exactly what we were in mind!
From my perspective, every project starts to deliver a value for business, from the very first day, either in pure business stories taken from backlog or in terms of infrastructure being a skeleton for whole business we cater. 




Now, let's focus on cybernetics, an extremely relevant and transdisciplinary science, rooted in ancient Greece and even earlier. Basically, it is an approach for exploring and examining regulatory systems in terms of their structure, constraints and possibilites. Cybernetics is only applicable when the system being analysed is involved in a closed signal loop. It means that actions done by the system causes some change in its environment and that change is fed to the system via information (feedback) that enables the system to change its behavior. Above description has two, valid points. First of all, cybernetics is a transdisciplinary science, which connotes a research strategy crossing many disciplinary boundaries, to create a holistic approach. This might be compared to generalization rule in OO languages. Secondly, definition focuses on feedback loop, as a main source of information for changing its behavior. Every scientist and discoverer may and should ask, if there is any principle or rule we can take from Cybernetics and apply it in Software Engineering?



Having all above knowledge in mind and treating it as a prerequisites let's do some cybernetic analysis and try to answer above question. Given every member of agile team is a distinct cybernetic system, equipped with some sort of feedback loop. Let's further assume that environment, we are deriving information from, is code base. Then the only unknown remains feedback loop. A source control management (SCM) tool might be perceived as a sort of feedback loop. 
Let's put under examination two very well known SCMs: SVN and Git. 
Probably all of us know what 'painful merges' are. We are exposed to them as we are breaking at least one of below rules (I was discussing that topic here):
  • Baby steps
  • Small scope of changes
  • Short living branches 

A rule of thumb is that SVN merges are not the most pleasant things we may do, in terms of development process. Because they are so, we do not tend to do them as frequent as we should. As a matter of fact, we end up with, say one merge per day, which is done in the morning, or even not that often. We are obviously breaking at least one of above rules and we might end up with something called a 'merge hell'!
On the other side, Git as an alternative SCM solution is having incorporated merging process (or rebasing if you like) into your day to day development cycle. Complying to rules allowing you to avoid painful merges and having Git on your side, enables you to commit more often, comparing to SVN. 
Let's come back to our cybernetic experiment and SCM as a parallel of feedback loop. How do you think, which SCM is better? Is it SVN with its clumsy funny merging process and rare synchronisation with remote repository or Git, which is pushing you to rebase frequently as a part of your development cycle? It is your choice, but remember about everyday pain of all people using strategy you have chosen!


Saturday, 1 September 2012

Basic development cycle in Git

This article is a short overview of Git and how it can be used in development.
I started to use Git, some time ago and almost same time I fell in love in it. Now, I know that I'm fully devoted to Git and I don't want to come back to SVN, any more. 
I don't want to slander SVN, as it solved majority of CVS drawbacks, which were teasing our industry. However, the thing is, Git is so much better, than SVN that honestly, I can't see the point of sticking to it, for even a minute longer, than I have to. SVN had its five minutes and used them in a pretty decent way. Now, it's time for the Git!
When it comes to Git's learning curve, it's not extremely steep. There is a well written book, titled GitPro, which shows all necessary concepts useful in every day development. If I were starting learning Git, I would read first three or four chapters, just to get a general idea what is the whole thing about.
In terms of architecture, the most influential decision made, was treating Git as a distributed Software Configuration Management (SCM) tool. That approach turned SVN's flaws into Git's virtues. Now, Git is boasting of its:
  • speed
  • failure resistance
  • spread backup
There is a very interesting observation showing that basing on a single design decision, Linus Torvalds got rid off all ridiculous issues we were heroically fighting with, in SVN. Let's quickly recap all of them and show how Git copes with his ancestors' cons:
Speed - there is no need to wait for syncing with remote repo, every single time you want to commit, as Git is using a local copy of remote repo. The only thing you do is occasionally pulling and pushing changes from/to remote repo.
Failure resistance - there is no concept of central repo, so during development process everybody has a copy of the whole, initial repo. Assuming destruction of one of the repos, the recovery is quick and easy. It bases on a copy of remote repo on other machines. It's much harder to loose all changes on all dev machines. As a consequence of one repo failure, there is no longer a tie up for all developers.
Spread backup - given the remote repo is down, you can still work on your local copy of remote branch and sync with remote one, when it's up and running.



Okay, let's get down to the business and show how basic, Git, development cycle may look like.
First of all, we would need a Git installed on our machine. Furthermore, a GitHub account would be a sort of must for us, too. We will use GitHub to set up a project and have a reliable remote repo. Everything is described on GitHub's bootcamp page, so I'm not diving into it.
When it's done, we have two options. We may start our project on our local machine and add it to remote repo or we can clone existing remote repository. To start a repository at current directory issue:
$ git init

If you like to copy, say remote repo, use:
$ git clone https://github.com/oskarkorczak/sample-repo.git

You are able to list all your repositories (local and remote), using below command:
$ git branch -a

Now, we would like to crete a separate branch and start developing our change:
$ git checkout -b name-of-the-new-branch

Basing on a small steps rule and TDD cycle, you would like to commit every single time you have a green test. In order to check, what changes are going to be tracked or potentially going to be committed issue:
$ git status

You can also commit whenever you feel you did something valuable in branch. That's as simple as saying to Git:
$ git commit -am "Here comes your commit message."

It basically adds your changes under version control (-a switch) and puts an inline message (-m switch).
If you would be curious what is happening in Git's history, you can always ask for it, by issuing commnad:
$ git log

Given that it took you one day to develop a change in your branch. Now, you would like to sync it with others and commit to remote repo. First of all, you have to switch to your local master branch, which is a local copy of remote master (main) branch:
$ git checkout master

Then, download all changes done by other developers to your local master branch:
$ git pull origin master

Origin is a default name of remote repository. It basically works like IP:port address pair in networks. Origin might be an equivalent of IP and port may be a branch name, in this case, it's master. Let's switch back to our branch:
$ git checkout name-of-the-new-branch

Now, we have to stop for a second and clarify how rebase works. In a nutshell, it's highly probable that there have been some commits of other developers. Rebase is a process of lining them up, so that all sync commits from last pull request from local master, would be before your local branch amendments. Simplifying, it means that rebase process will put all your changes at the end of updated master branch.
$ git rebase master

If it happen that you would have some confilcts, rebase command will stop at the first conflit and notify you about that. You have to resolve all conflicts manually or alternatively you can install a merge tool. Resolving process is a step similar to SVN. You have to go to particular file, delete unnecessary entires and tell Git it's done, by adding new changes under version control:
$ git add resolved-file-names

Then, you have to prod Git to carry on rebasing your changes with local master by:
$ git rebase --continue

If you forgot about adding something to the code, you are always able to abort rebasing by:
$ git rebase --abort

After that, it's time to send your branch to GitHub, where it could be picked up by some Continuous Integration system for building and testing purposes.
$ git push origin name-of-the-new-branch

When all tests are green you can raise a pull request. On GitHub it's simple, you are switching to your branch, pressing a "Pull Request" button and it's done. You're getting a link to pull request, which might be send to all developers to be reviewed. When code review is done, your pull request might be merged with remote master automatically by pressing a "Merge" button in pull request. There might be also a case that between the moment you send your changes to GitHub and hitting "Merge" button, somebody else merged his changes in overlapping area of the project. Then, there couldn't be done a fast-forward merge, which means repeating a part of above sequence of steps. You will have to update your local master, do the rebase and once again send updated branch to GitHub. Another "push" will update exiting GitHub's branch automatically. "Merge" button is available once again.


Assuming that you smoothly went through code review and merging procedure, the last thing you should do is cleanup. Remote branch is no longer necessary and it shouldn't clutter remote repository, so we are going to delete it:

$ git push origin :name-of-the-new-branch

To be honest, deleting remote branch is a bit dodgy for me. Who the heck invented colon before branch name as a deletion marker? A sort of -d switch is more natural, isn't it?
On the other hand, removing local branch is totally different and is done by command:
$ git branch -d name-of-the-new-branch

There are also two more, very useful Git commands. First one is responsible for fetching all remotes to local repo:
$ git pull --all

Second one is removing from local repo all branches, which are not existing on remote repository:
$ git remote prune origin

Later on, say next day, when your code base is changed by other team members, you can call a chain of useful commands. They will update master and all other branches, clean branches no longer maintained on remote repo and list local and remote branches, which are currently used. All these things might be done by invoking commands you already know:
$ git pull origin master; git pull --all; git remote prune origin; git br -a

At this point, you should know whole, basic Git development cycle. 


There are also couple of golden rules related to development as such. They are especially useful while working with Git:

  1. Baby steps - use TDD and commit every single time you have a green test.
  2. Small scope of changes - keep your changes as small as possible, not to affect many places in the code base. It prevents your changes from alternating between you and other developers.
  3. Short living branches - tightly connected with above point. The longer branch lives, the more vulnerable it is for not merging in a fast-forward mode.