Sunday, September 28, 2014

Programmer's Diary: Constructing your Tests Line by Line

It is a different thought process for everyone, but when I write the tests that will represent the functionality I am about to implement, I always start with the Exercise or Act part.

A unit test is usually composed of three or four parts, thus the rule of 4As

1. Setup or Arrange
2. Exercise or Act
3. Verify or Assert
4. Tear down or Annihilate (this may be missing, automatic garbage collection, anyone?)

I observed that people who know about these parts have the natural tendency to start writing a test in that exact order. They start by asking themselves "What do I need?" and only then "What do I do?". This frequently leads to dilemmas that can not  be answered, and they just give up writing the test and start writing the production code.

In my opinion this type of thinking has a fundamental flaw. You cannot know what do you need before you first figure out what do you want to do. That is why I always start with 2. Exercise or Act. And my second step is always 3. Verify or Assert. This way I can put down the basis of the test by clearly defining what I want to do and what results I am expecting.

I build the 1. Setup or Arrange part as an iterative process by adding all the required dependencies for the already defined lines. Finally I do 4. Tear down or Annihilate to do the opposite of setup if needed.

1. Write a new test function and name it by the behavior you want to test.

function testItCanAddTwoNumbers() {

}

2. Act! Do the behavior you just defined in the test's name.

function testItCanAddTwoNumbers() {
    $sum = $calculator->add($n1, $n2);
}

3. Assert.

function testItCanAddTwoNumbers() {
    $actualSum = $calculator->add($n1, $n2);
    $this->assertEquals($expectedSum, $actualSum);
}

4. Arrange, or prepare all the missing parts.

function testItCanAddTwoNumbers() {
    $calculator = new Calculator();
    $n1 = 1;
    $n2 = 2;
    $expectedSum = 3;

    $actualSum = $calculator->add($n1, $n2);
    $this->assertEquals($expectedSum, $actualSum);
}

5. Annihilate, or destroy persistent information. Nothing to be done for this part here.

That's it. Have fun writing tests instead of hitting a brick wall with your head!

Saturday, August 30, 2014

Programmer's Diary: Finding Your Ways

I usually tend to give any advice with a pinch of salt. In one of my tutorials about SOLID I wrote the following phrase: "As with any other principle, try not to think about everything from before."

Which led to some dilemmas with a few of my readers, especially because it was in the Interface Segregation Principle article. I answered the questions of the reader, but I think the ideas there merit a blog post. So, here it is. Read on.

Any exaggeration is bad. If you think about everything upfront, it is bad. If you think about nothing upfront, it is also bad. Finding the right balance in what to do and what to postpone or not to do at all is essential for every project. There is no universal theorem or solution. There are however some recommendations that try to keep us on the right track.

In Agile software development, you will mostly meet tow concept. Each of them is pulling back you from one of the two extremes mentioned above.

1) Postpone everything to the last responsible moment. If you apply this, you may ask yourself every time you make an interface: should I create the interface? Will there be more than one implementation? If yes, what and when that implementation will be? Is it more expensive for me to delay the release by 2 hours and implement the interfaces now, or it is more expansive to not write any interface and introduce them on the next release when I know I will need them? How sure I am that I will need the interface on the next release? Can the plan be changed, outside of my control, so that I end up with a code that will never be relevant?

2) Program with change in mind. If not from the first release, then from the second. If you needed to change a specific piece of code, than there is quite a big chance you will need to change it again. On your first change, make it so that your third, forth, and so on, changes will be easy. If you see some code, once written and never modified, and you have no reason to change it, don't.

Basically this is it. Now you may ask yourself how to deal with these problems? You have three possible ways to go on:

1) Take the postpone extreme. Postpone everything, until you feel it starts to heart. Than, gradually try to think a little bit ahead and don't postpone things quite as much. This is how we at Syneto started.

2) Take the plan for everything extreme, and evolve from there. This is actually one of the routes many people take when coming from Waterfall. Gradually try to identify parts that take up a long time in planning but proved to be marginally important. Continue doing so until you feel pleased with your process, and you don't feel that what you do will never be used or useful.

3) Take the middle road. This may sound attractively optimal, but it is not. I don't think any project is right in the middle between the extremes. You can take the middle road, and continually think about both extremes. With time you will find toward which end your project requires more attention.

Sunday, July 20, 2014

Watch, Learn, Do, Decide

I have this concept whenever I need to decide if something new is good or not for me.

First I watch or read about the idea.  Then I study more about it. Then I do it for a relatively long time. Then I decide if it is good or not for me, that I should drop it all or I can adopt parts of it in my life.

This applies exceptionally well to new programming techniques.

At work, at Syneto, we usually do things for about 6 months before we decide.  But those are big things.  They affect a bunch of people.

In my personal life I scale down. Both the discovered things and the time for doing. Still, I always make sure I don't decide too early.

Recently I was invited to a new developers forum in my country. And after just one day,  I am amazed how many people jump over the learn and do part. They only watch and decide.

I believe the only way to decide upon a thing is by past experience. But you need to build that experience yourself. You can't avoid it, at least not for a long time.


Sunday, May 18, 2014

Belgrade CityBreak: An Unexpected Journey

My wife and I had an unplanned opportunity to visit Belgrade for the first time. It went pretty well.

We were asked to drive two of my colleagues to the Belgrade airport from where they took a plane to Paris. This trip allowed us to stop in Belgrade and visit the city. We had no plans, no knowledge about the city. I just set "Belgrade City Center" in the GPS and let it drive us ... somewhere.

First of all, parking your car in Belgrade is extremely difficult. We almost gave up after 30 minutes of randomly choosing streets in the central area and trying to find a spot to stop. Finally, we managed to park, at about 2.5 kms away from the point marked as city center on the GPS. Well, a 20 minutes walk should not be that much. But we were so hungry, and finding a restaurant was a bigger than expected challenge. We did not know the city, but based on the look of the streets and shops, we were somewhere close the center. There were even quite a lot terasses, but only coffe and drinks served. Where are the restaurants?

After trying several alleys that seemed promising, and having no luck at all finding a restaurant, we went on on the main street and finally ended up in the pedestrian area. At least finding a restaurant there was not a challenge any more. We ate at a random restaurant called Opera. They had good food and decent prices. One starter, two main courses, some mineral water and two coffees = 40 Euro.


After we ate, and with our bellies full, we decided that it was a really good time to just walk and admire the city and whatever surprises it may hide. The weather was also a good company, about 25 degrees, mostly sunny. Luckily the restaurant had free WiFi, so we had a chance to look up the surrounding attractions on TripAdvisor. Choosing our next stop was simple. The old City Fortress was just a few minutes away.


What we didn't expect is it to be so well preserved, free to visit, and really impressive. It is bigger than you may think at first sight and spending an hour or so just by walking around the old streets, walls, is not even enough. There is also a great public park surrounding the whole fortress. You can relax on a bench, walk around in a well maintained garden, do some sports, or just stop for a coffee at the Danube's bank.


An expo with first and second world war military equipment was just an amazing plus for this visit. So it's time to wrap up some pros and cons.


PROS:

  • Mixed architecture - there were streets on which you could recognize 4-5 types of different architecture from different eras. From a princesses house, through a peasant's house and a communist office building to victorian architecture. All you could imagine on a single street. There were also places with fluent uniform nice architecture.
  • Food was good - even though we have chosen a restaurant at random and we ordered Serbian specialties we never ate before, we liked the food.
  • People are friendly - we felt the local people friendly, quiet, helpful.


CONS:
  • Difficult to find a restaurant - unless you are in the very city center, on the pedestrian area, even a McDonalds or other fast-food is hard to find. You can get coffee and drinks, but now food.
  • Difficult to find a mini-market - on the whole 2-3 km walk from the car to the city center and back, we found a single mini-market to by some mineral water and cigarettes. Yes, there are kiosks here-and-there, but paying with your credit card is not an option there.
  • Traffic is quite intense - even though it was Sunday, there was quite heavy traffic in the city. Where did all that people had to go by car on Sunday? I can't understand...

That's it. Thanks for reading.





Friday, May 2, 2014

Agile by Instinct

There is a question on my mind for some time now. An idea, a thing that just can't let me alone.

What do you do after you tried all agile practices?

I had the opportunity to work for a company that went through a great deal of change by giving up an old-style waterfall oriented management and adopting agile. But what adopting agile actually means?

As any company and team we started by learning new techniques and practices. We started to plan our work on a board and we did a group-reading marathon of Gerard Maszaros' xUnit Patterns book. This was about 4-5 years ago, and it was enough to rise our interest in all these new things. We went on and adopted TDD and we still use it at a daily bases. We redesigned our architecture so that our business logic is isolated from the rest of the system as Robert C. Martin recommends in his clean architecture concepts.

We implemented a continuous integration and deployment system for our project, we covered most of our code by tests, we even optimized the whole deployment process to an extent that it takes about four and a half minutes to run all the 6000+ assertions in our unit tests, all the MVC framework's controller, helper and model tests (these are just a few, but still), compile and encode everything, crate packages and publish them on an update server. I think we have a process that is quite optimized. Even though there may be small changes to make, there will be no more significant gains.

And our everyday software development process? Well, after doing SCRUM for a while we tried Lean with Kanban. From all of them we devised the parts that can the most help our processes. There is not really any other formalized process we could try and fit in our management structure.

Continuous learning and deliberate discovery are another two things we do frequently. We, as professionals try to make ourselves better, each day, every day. We do courses, we practice at home, we attend conferences, we organize events, and so on.

"It sounds like a success story" as Dan North remarked it when I was talking with him about this topic. But what do we do next? What is the next thing we can try to make our process better, to go faster.

An interesting question Dan North asked me, and I was quite surprised by it, was "What makes you think you can go faster or better? Maybe you reached your maximum speed." (approximate quote). I couldn't answer him then. In retrospective that is because I have no rational reason to sustain my desire to go faster and better. But my instincts tell me we can do better. My professionalism tells me I can learn more and take better decisions. I am asking myself instead "Why should we ever stop getting faster and better?" Of course there is no magic answer. If there would be, it would be a formalized practice or technique, and this blog post would not exist.

For the time being I feel we are far from perfect. In the past year or so we tried to orient our attention more toward our clients. We tried and successfully listened to other departments. Now we are on our path to create a better synergy between dev, sales, operations, and marketing. And this is why Dan North's suggestion surprised me most. He suggested the exact same thing.

So, after you go through all the practices and techniques of agile development and you make them work for you, you must start being truly agile.

Being agile is not about adopting rules and practices. Being agile is not even about learning and devising your best way to work based on those processes.

Being agile is to learn, as a team, as a company, to follow your instinct in order to value individuals and interactions, to create working software, to listen to your customers and to respond to their needs as quickly as possible.

Agile is about us making efforts so that others doesn't have to.


Monday, April 28, 2014

#CraftConf Budapest 2014. A Big Wow!

At the end of April 2014 I went to a conference. CraftConf Budapest. We had no idea how many attendees will there be or how big the event will be, but one thing was sure, there will be a panel I've never seen in Europe at any conference before. There were so many famous people invited to speak that the event became a must-go both for me and for my colleagues.

We will write a more extensive blog post on Syneto's blog, so here I will present only my personal impressions.



First impression: This is a huge event!
I never attended such a big conference. There were more than 900 attendees and the main room had 5 screens, the big one, in the centre on the image above was 10 meters or so in diagonal. They also managed to secure some very wealthy sponsors who kept our bellies full and prevented our mouth to dry out. The other 2 rooms were smaller, but still impressive.



Second impression: There at most 5% of new information in a talk.
For whatever reason I had huge expectations from this conference. However I have to realize that a talk can not contain more than 5% new and useful information. At least not for me and my colleagues. This was a hard thing to realize, but it led to the next one.


Third impression: The value of a conference is in the chance of speaking with famous people.
Yes. You need some guts, but if you want real value for the money you payed for the conference, you must go and talk with those important people. For some I had questions in order to obtain new information, for others just to confirm some of my own ideas and perceptions and for other I actually managed to provide constructive feedback.

All in all I talked with more famous people in 2 days than in my whole life altogether. So I thank you Bruce Eckel, Dan North, Eric Evens, Gerard Meszaros, Theo Schlossnagle, John Hughes, Simon Brown for your time and for every other speaker for their great talks.

Monday, March 24, 2014

I Don't Believe in Genetically Born Leaders

I hear so many times that some are made to lead, while others to follow. And while there may be some truth in that statement I don't believe someone can born to be a leader. I believe in discipline. I believe in hard work. I believe in fulfilling of dreams. I believe any of us can lead or can be led. I believe it is ultimately our choice. But how is that possible? Don't we have different personalities? Don't we have different professional objectives? Don't we have different dreams? Don't we born and live in different societies? Sure, we have, we are, we do. Than how could any of us become a leader or a follower? Well, society, family, and friends have a great impact, but at the end of the day it's up to you what to choose to do. Some choose to follow and be happy. Others choose to lead. Others try to find the balance between the two. I believe when there is someone to follow, you should do so. However, when there are some to lead, you should do so again. There is no way you can't be leaders for some and follow others. This is the only natural situation you can be in. There will always be things to learn from those smarter and wiser than you, and there almost always will be others willing to learn from you. If you only want to be a follower, you will never feel the appreciation and amazement of other young minds discovering your secrets. If you only lead, you will burn out very quickly. Your students and followers, if balanced between the two characters, will simply become smarter and wiser than you and will become leaders instead of you. That's why the most depressive persons I ever seen were followers without will to lead, or fallen leaders without hope to rise again.

Wednesday, February 19, 2014

Programmer's Diary: Transforming PHP Objects to Strings


In my upcoming programming course for +Nettuts+  I will implement a persistence layer for the application developed throughout the course. For the sake of simplicity I decided to make it a file persistence and keep information in plain text. This was a good occasion to use a nice PHP trick to convert simple objects into plain text.

Our objects are books and besides the fact that there is an abstract book class there are a lot of specific implementations for different kind of books, like novels. Each is a little different than the other, so saving all the books in the same text format would have been impossible.

PHP offers a magic method called __toString(). Creating an implementation for this method, on any object, will allow you to use that object in a string context. Let's see a basic example.

class SystemInformation {

 private $cpu;
 private $ram;

 function __construct($cpu, $ram) {
  $this->cpu = $cpu;
  $this->ram = $ram;
 }

 function __toString() {
  return "CPU: " . $this->cpu . "%" .
        "\nMemory: " . $this->ram . "MB";
 }
}

If we create such an object and try to run it in a string context, like in echo(), it will be automatically converted to string, using whatever we return in __toString().

$sysInfo = new SystemInformation(40,1024);
echo $sysInfo;

This will output:

CPU: 40%
Memory: 1024MB

You can also use it in some other contexts also, for example this test will pass just fine:

$this->assertTrue(strpos($sysInfo, 'CPU') !== false);

And when PHP is not smart enough to figure out that you want the object as string, you can always call __toString() on it directly.

$this->assertRegExp('/CPU/', $sysInfo->__toString());

For the complete example with the whole application I mentioned at the beginning, keep an eye on the +Nettuts+ premium courses. Have a nice day of programming.

Wednesday, February 5, 2014

The advantages of working for 2 companies at the same time

Many companies deny their employees to have a second workplace, or work as freelancers in the professional domain as their main job. Other corporations have an approval procedure,  and each employee must declare any other job he or she wants to take. If the company decides that the job may conflict with its interests, it may deny the employee to accept it.
What companies rarely consider are the reciprocal benefits. I had 2 workplaces almost all my career. Right now I work for Syneto and in my free time I write for NetTuts. This is great for everyone. I can write great articles based on my experience at Syneto. Syneto benefits of me becoming a better programmer with each article or course I make. Explaining my ideas greatly improves my knowledge on that specific domain because I need to dive into details about it.
So, I learn more and better, Syneto gets better code and NetTuts better articles.

Everyone wins.

Sunday, February 2, 2014

Programmer's Diary: Writing a Series for @NetTuts


If you are following me on twitter you probably know I am a regular technical writer for +Nettuts+ . I write various tutorials and articles on programming topics. However I never wrote a series with tutorials that are connected in one way or another.

That changed with the series on the SOLID principles. I had to write four articles covering five principles and I found out there are quite a few challenges when writing a series of articles.

Challenge #1 - The first article must be good. Much better than any of my stand-alone articles, because it must convince any reader, new or regular, that the upcoming articles in the series deserve their attention. The first article has the stake of the whole series. If it fails, there is a chance the rest will never be read, doesn't matter how well written it may be.

Challenge #2 - Each article must find a way to refer to, to connect with the previous articles or at least with some of them so that the readers have a feeling of continuity. In each of my SOLID articles I referred to at least one, but preferably two other SOLID principles. Now, this is again tricky. Because the articles are published and read in sequence, from S to D, even though O may relate to I or D, in the article itself I can only refer to S because the reader may not know about the LID principles. If I refer to any of LID I risk one of two things: confusing the reader and loosing him/her, making the reader curious and making him/her read the three LID principles from other sources and not read my upcoming three articles.

Challenge #3 - Each article must be self contained, in a sense that a new reader must be able to comprehend it without reading any of the preceding or upcoming articles in the series.

Challenge #4 - Each article must provide something different so that the readers don't get bored. If one article explained the concepts with mostly text in anecdotal manner, the next one must use a different approach, maybe more schemas or more source code or more quotes of rules and definitions or more funny statements. It doesn't really matter what, but it must be different, it must be unique in a way to disrupt the monotony of the series and still provide the valuable information it proposed as its topic.

Challenge #5 - The last article must contain a conclusion to the whole series. It must be written in a way that not only transfers the last topic in the series, but also connects all the dots and provides a high level view over all the topics presented throughout each tutorial. It also has to put everything in perspective, under a different light, in a different - bigger - universe, where the whole series is just a small piece of the puzzle.


That's why I concluded my series about the SOLID principles with a reference to The Magical Number Seven, Plus or Minus Two and that is why there are 5 challenges in this blog post.

Sunday, January 19, 2014

Programmer's Diary: Mistakes Will Come Bite You in The Butt

Last week I was doing a quick refactoring of our virtualization module at work. We are about to introduce some new concepts in it and a reorganization of the directory structure was due.

However, this being a quite mature project it was started before the dawn of namespaces in PHP and the KVM module was also written in that fashion. As we thrive for perfectness whenever we can, moving the module to namespaces while changing the directory structure was the obvious choice.

Introducing namespacing into a module of about 20 or so classes was not a big deal. Tests covered most of it, find and replace worked like a charm and the PHP analyzer in PHPStorm highlighted a the few spots missed by the former two actions.

In less then a full work day the whole module, at the business logic level, was up and running using namespaces and the new directory structure. Long live TDD and good test coverage, it would have taken several days or maybe weeks to change all that without tests, but that's another story, for another time.

Then my colleague +Vadim Comanescu  offered to help with the update of the web interface. As our business logic is totally separated from our user interface, the changes should have been quite localized. And they were, for the most of it. The change went on smoothly, except one little mistake - or laziness for that matter - we made a few months ago. 

A rogue method in a view helper implemented something like "isCurrentPathForVM($path)" At first sight it was acceptable. It accessed the virtual machine inventory class Kvm_VmInventory, retrieved all the virtual machines with its "findAll()" method and did a quick foreach() on it asking each virtual machine if it belongs or not to the provided path.

Helper -> Inventory -> Virtual Machine. A simple dependency chain involving only 3 classes. Shouldn't be a problem, right?

Then it struck us! Why modifying the public interface of the Inventory class affects a view helper? Why the internal class structure of the KVM module is leaked to the UI? Why a helper attached to a view must know the working details of an class buried deep inside the module? Don't we have a Facade already written for that?

So many question had been risen in an instance. Clearly something was wrong.

A view helper should use only information available to the view and it should only do operations related to presentation. Yes, it should contain logic, but only presentation logic. Was finding out that the current path belongs or not to a virtual machine presentation logic? It turns out it was not.

To start answering our so many questions we decided the helper must not know about the inner classes of the KVM module. However it needs to ask the module for the information it requires: Does the current path belong or not to a virtual machine. If yes, the helper will instruct the view to draw a little computer instead of the folder icon at the left of the path.

To do so the helper need access to the facade. But should it create an instance of the facade? No, it shouldn't. There is already one available created by the Kvm model. But accessing a model from a view helper is again tricky and wrong. The helper needs to take it's parameters from the view.

The view's parameters are defined by the controller. That's great, we have the missing piece in the chain.

Helper -> View -> Controller -> Model -> Facade -> Inventory -> Virtual Machine. Here is our new dependency chain. Much longer, but also way more decoupled and correct. The model provides the facade to the controller and passes it to the view, subsequently letting the helper ask for the question: is the current path for a virtual machine? Which made us realize a distant code duplication was also present. The whole logic of the original method was already implemented in the facade. 

We were pleased to also a remove a code duplication that lingered hidden in the dependency chain.

Finally we moved the logic from the facade to the Inventory. Facade's should have no logic, they should only be a common entry point to the module providing an easy to understand specialized public interface to any client.

All that done, Vadim and I looked at each other, and he said: "There was not one instance when a mistake or laziness did not come and bite us in the butt afterwards!"

We at Syneto always try to make our code better. We are proud of our accomplishments and we are not afraid to acknowledge our mistakes.

Disclaimer: Code descriptions, method names, functionality details are approximate in order to protect our project.


Thursday, December 26, 2013

End-of-Year Review: Economic Flashbacks


At the end of each year we tend look back and analyze what has happened. In this post I will rent about economics and the financial crisis again.

It has been another year when all over the news, and in society in general, the financial crisis was a constant topic. We were, again, told that even though things seems to be going a little better we are still in a crisis and we, as a society, have to endure and support each other and accept low salary, extra hours, no Christmas bonuses, and so on.

Fortunately for me, I work for an open minded and realistic company. The rules are simple, if the company does well, the employees do well. If the company doesn't do well, we, the employees will do our best to make it better. However this is not the case for most of the companies in my country, that is Romania.

In my personal opinion there was never a crisis in Romania. At least not directly. We felt the effects of the crisis as exports dropped and banks decided to not loan people and divert all the incomes to their mother countries. But that's it. There were no huge surprises or bankruptcies. There were no big companies closed and unemployment is kept in check at one of the lowest levels in Europe.

However, the curtain of the phrase "We don't have money, it's a crisis!" allowed a lot of companies and politicians to hide behind those words and affect a huge part of the country's population. We knew politicians were stealing huge amount of money, but simple citizens and the media could do little. The president itself may very well be the heart of groups making money end up in the pockets of well placed, influential people. Of course, there are little or no proof, but that's how things work. Take for example the 10 billion dollars payed by the state for a highway that was never built and the money never recovered. Money doesn't evaporate.

So, in the early years of the crisis the government, back then controlled by the democrats, decided to reduce all the salaries and even pensions (though illegally). There was less money coming in to the state's treasury since less exports and external investments reduced the growth we were used to. We, the citizens, thought it will make the politicians steal less. It did not. They stolen probably even more, thinking about the dark times to come, and took away from the people. Well, they payed the price at last year's election, finally they were gone.

2013 was the first full year with a social-liberal-democratic government. An unlikely alliance with one goal, get rid of the democrats and the actual president. They managed the former, unfortunately not the later. I am sure they are also money hungry, and making their part in all of the state's businesses, but at least we stopped hearing about briberies like 40% of a 1 billion dollars highway must go to certain people otherwise the project is assigned to another company willing to pay. We also could observe some legal changes toward a better direction. We've seen that most of the salaries and pensions were reintegrated to the values they had back in 2010 when they were reduced. Some of the illegal cuts were also payed back retroactively.

We also registered a 3-4% economic growth. A very nice figure in my opinion. And an absorption of about 30% of the European funds, compared to about 5% in 2012. A lot of money.

Even though I still do not agree with at least half of the government's actions, at least I can see some of them are good and they are starting to produce positive results.

The private sector is a totally different story. Private companies can do whatever they want and believe me, they are doing huge profits, hidden under the curtain of the crisis slogan. About 40-45% of all the employees in the private sector are working the minimum salary imposed by the law. That is about $250 per month. And from that you have to subtract about 20-30% of different taxes. At the other end of the scale, there are only 2.5% that are earning more than twice the average monthly salary, which is somewhere at 500-600 dollars.

Most employees are kept in the dark, and if they dare to ask for a rise they are simply told "It's a crisis.". Meanwhile many companies are reporting record profits. The people, a huge part of the country's working force, thinks there is no other way, they have to work for the minimum wage. They gave up ... unfortunately.

And the banks are part of all this. They are in no trouble, at least not here in Romania. They probably never were. They are doing just fine. In fact I think they feel very well. All those house loans given before the house crisis are paying off. People continue to pay them. And while in many countries the interest rates were reduced to almost zero, they stayed more or less the same here, except the effects of the mandatory EURIBOR or ROBOR interest rates, which were reduced. But the banks are actually taking more than before. For example, when I bought my  house I payed about 5% EURIBOR + 3% the banks interest rate. Now, EURIBOR 0.3% and the bank's rate is about 4-6%. Yes, I pay less than in 2008, but the bank is getting more.

So, the banks are getting richer and more wealthy while telling us that we should be happy we pay less then before ... sure.

And the proof? Simple. Basically you can not get loans now. The banks are giving only very few loans or only those that are guaranteed by the state. For example if you want to by a car and you have a salary in the top 2.5% of the incomes, you have little chance to buy anything but the cheapest cars out there (I refer to new cars). It doesn't matter you could easily pay the car in less then 2 years, they will not risk it. Why should they? They can sit back, do nothing for the next 20-30 years while all those huge house loans will be payed. Good business. They are still supporting small credits, 200-300 dollars if you want refrigerator or a new TV or a new phone, but basically that's it. And they are doing that because the risk basically is zero. If you don't pay, the law permits them to take 30% or so of your salary and they will, in a couple of years, get the money back. And if they wont, they've lost almost nothing anyway.

So, it is so sad when you can see through the curtain of the crisis and see how so many people are exploited unjustly and kept working for minimum wage just because there is a fictional crisis out there...


Friday, December 20, 2013

Programmer's Diary: The Bluetooth Hell Continues on Linux

In my previous post I described an elaborate way to configure your bluetooth device on the badly behaving Bluez and newer kernels. Well, things seems to be changing again.

My distribution, Sabayon, pushed yesterday a newer pre-release of Bluez 5.... something. Now pairing actually works from KDE, however the bluetooth service segfaults when I connect my keyboard. Mouse connects though without a problem.

What is even funnier is that even though the service goes bye-bye, and I can not remove or add devices, once connected both mouse and keyboard works, with the service crashed!


csaba ~ # systemctl status bluetooth
bluetooth.service - Bluetooth service
   Loaded: loaded (/usr/lib64/systemd/system/bluetooth.service; enabled)
   Active: failed (Result: signal) since Fri 2013-12-20 19:08:15 EET; 14s ago
     Docs: man:bluetoothd(8)
  Process: 20461 ExecStart=/usr/libexec/bluetooth/bluetoothd (code=killed, signal=SEGV)
   Status: "Running"

Dec 20 19:08:01 csaba bluetoothd[20461]: Bluetooth daemon 5.12
Dec 20 19:08:01 csaba bluetoothd[20461]: Starting SDP server
Dec 20 19:08:01 csaba systemd[1]: Started Bluetooth service.
Dec 20 19:08:01 csaba bluetoothd[20461]: Bluetooth management interface 1.3 initialized
Dec 20 19:08:15 csaba systemd[1]: bluetooth.service: main process exited, code=killed, status=11/SEGV
Dec 20 19:08:15 csaba systemd[1]: Unit bluetooth.service entered failed state.

So it seems to be no problem, right? If the service crashes after my devices manage to connect, all I have to be careful about is to first connect my mouse, and only then my keyboard. Wrong! Bluetooth devices have this habit of entering in a sleep mode after a few minutes, so they reconnect automatically after an idle period of time when moved or touched. I must have my service up and running at that point.

In lack of a better idea ... I mean in lack of a lot of free time, because ideas I have plenty, here is a one liner crontab entry that will issue a start to your bluetooth daemon. Just put it in /etc/crontab


* * * * *       root    systemctl start bluetooth

If the service is already running, start will do nothing, if it does not, it will start it. Still, I have to remember to enable my mouse first, but in the worst case scenario I will need to wait one minute to connect the keyboard... or grab my other, non-bluetooth, keyboard and restart the service.


Monday, December 16, 2013

Linux Tip: How to Pair your Bluetooth Device when Using Bluez 5.x and Kernel 3.11-12


It seems like there are problems with Bluez 5.x and newer kernels, especially post 3.10 ones. Since 3.13 is not yet out, these tips apply to kernel 3.11 and 3.12.

I specifically tested and applied the solution below to pair my Microsoft keyboard and mouse. My specifications are as follows:

[bluetooth]# version
Version 5.10
csaba ~ # uname -a
Linux csaba 3.12.0-sabayon #1 SMP Tue Dec 3 15:10:14 UTC 2013 x86_64 Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz GenuineIntel GNU/Linux

So if you were looking for things like:
I can't pair my bluetooth keyboard on Linux
My bluetooth mouse won't work on newer kernel
My bluetooth headset pairs but doesn't connect
My phone can be discovered but not connected or paired over bluetooth
... then here is how to do it with bluetoothctl.

csaba ~ # bluetoothctl 
[NEW] Controller 00:15:83:3D:0A:57 csaba-0 [default]
[NEW] Device 7C:1E:52:A8:47:74 Microsoft Bluetooth Mobile Keyboard 6000

Start bluetoothctl. Mine found the keyboard automatically with it set in discoverable mode. However, it is possible you will need to enable scanning. Just write:

[bluetooth]# scan on

If it is not showing up at this point, you may have problems with your bluetooth receiver or the device is not set in discoverable mode (with that "connect" button pressed).

After my device was found I wen on immediately and tried to pair it. However, it asked for no PIN or anything, it just timed out with an error that I failed to provide correct PIN code. This made me think, maybe I missed something. And I did.

[bluetooth]# default-agent
No agent is registered

There was no default-agent. Now, I do not exactly know what these agents are, so if you know, feel free to comment below with details. However we can easily start one.

[bluetooth]# agent on
Agent registered

And we try to pair now...

[bluetooth]# pair 7C:1E:52:A8:47:74
Attempting to pair with 7C:1E:52:A8:47:74
[CHG] Device 7C:1E:52:A8:47:74 Connected: yes
[agent] PIN code: 241178
[CHG] Device 7C:1E:52:A8:47:74 Modalias: usb:v045Ep0762d0013
[CHG] Device 7C:1E:52:A8:47:74 Modalias: usb:v045Ep0762d0013
[CHG] Device 7C:1E:52:A8:47:74 UUIDs has unsupported type
[CHG] Device 7C:1E:52:A8:47:74 Paired: yes
Pairing successful
[CHG] Device 7C:1E:52:A8:47:74 Connected: no

So we are halfway there. Paired, but not yet connected. I also noted at this point, that the "connecting" LEDs on my devices were still blinking. So the keyboard and mouse did not yet know about the computer. But I could see them...

[bluetooth]# info 7C:1E:52:A8:47:74
Device 7C:1E:52:A8:47:74
        Name: Microsoft Bluetooth Mobile Keyboard 6000
        Alias: Microsoft Bluetooth Mobile Keyboard 6000
        Class: 0x002540
        Icon: input-keyboard
        Paired: yes
        Trusted: no
        Blocked: no
        Connected: no
        LegacyPairing: yes
        UUID: Service Discovery Serve.. (00001000-0000-1000-8000-00805f9b34fb)
        UUID: Human Interface Device... (00001124-0000-1000-8000-00805f9b34fb)
        UUID: PnP Information           (00001200-0000-1000-8000-00805f9b34fb)
        Modalias: usb:v045Ep0762d0013

So I went on and trusted the device.

[bluetooth]# trust 7C:1E:52:A8:47:74
[CHG] Device 7C:1E:52:A8:47:74 Trusted: yes
Changing 7C:1E:52:A8:47:74 trust succeeded

Then connecting worked. The blinking LEDs turned off. Great. And the connection remained ON.

[bluetooth]# connect 7C:1E:52:A8:47:74
Attempting to connect to 7C:1E:52:A8:47:74
[CHG] Device 7C:1E:52:A8:47:74 Connected: yes
Connection successful
[CHG] Device 7C:1E:52:A8:47:74 Modalias: usb:v045Ep0762d0013
[CHG] Device 7C:1E:52:A8:47:74 Modalias: usb:v045Ep0762d0013

I did reboot my computer and the settings are persistent. I know these devices are working correctly on my computer, I had them paired and working for the past year or so. In fact, if you had them paired before you upgraded to 3.11-12 kernels, you will have them working. Only pairing fails.

I could not find out a way to make pairing work from KDE or other desktop environments.

I hope I could help some of you, and save you some precious time.

Have a nice day.

Saturday, December 14, 2013

Programmer's Diary: Global Day of Code Retreat Retrospective

This year, 2013, I was the one organizing the Global Day of Code Retreat event in Timisoara, Romania. It was an amazing day and this is a small article to show everyone how I perceived the event.


First the Bad Things
  1. I felt quite under pressure, especially at the beginning, so many things to think about...
  2. We almost remained without food ... I forgot to order it in time. Crazy!
  3. There were less then expected people :(
Now the Good Things:
  1. I learned a great deal about facilitating and organizing events.
  2. The event went well, we managed to ditch all obstacles.
  3. I was amazed how well some participants perceived the event.

And now let's talk about what actually happened throughout the day. I planned for 6 sessions, we managed to do 5. I thought there will be quite a few people familiar with TDD, there were probably 1-2. But that is not important, we felt good, programmed and learned a lot.


Below are some of the most memorable quotes from attendees, told at the closing circle. I am proud of each of them, and I am proud I could help them open their minds to new concepts and ideas.

What did you learn today?

"There are different, successful ways to write software."
"It was the first time I actually did TDD so I learned quite lot about the process itself."
"Maybe we should think about more designing tests and less about designing code."

What surprised you the most today?

"I could write working code without the debugger."
"In the last session I felt my mind blowing. I managed to finally think about tests without thinking about all the production code's design. It was amazing."

What will you do differently next time?

"I will start reading some books."
"I will start learning other programming languages to understand the philosophy behind their culture."
"I will try to write more often tests before code and not after."
"I will try out some coding katas."
"I will try to take baby steps and let my tests guide my design."
"I will research a good testing framework for .NET."

*quotes are approximate



I am proud I could today facilitate an event where programmers had the opportunity to learn and they took it and learned great things. I was surprised and pleased by their dedication and openness and they also started quite interesting discussions which led to short brainstorming mini-sessions.

Total headcount:
~7 people from Serbia
~7 people from Timisoara

~7 kids from Coder Dojo (thank you for joining us, it was great)

   2 people from Macedonia
   1 person from Germany
+ 3 organizers and facilitators

I am happy I've met you. See you next year!



Saturday, November 9, 2013

Programmer's Diary: Interface Naming

This is a repost from my old blog. Original post date March 15, 2013


There was a twitter thread recently about interface naming. How should you name your interfaces? "IProduct" or "ProductInterface" or in another way? To my surprise the majority of the people who replied to that thread suggested "ProductInterface" and than "IProduct".

I suggested simply "Product".

In my view an interface should be named to reflect an abstraction. When you decided to make an interface you had a good reason to do so. If you didn't, your interface has no reason to exist.

In most cases interfaces abstract a higher, more general concept and they have several implementations. Of course, you can't write two implementationa at once, so at the beginning you will have only one implementation, then when you need another you will have another one.

Let me give you an example from our code at work. One of my colleagues, +Vadim Comanescu , wrote some logic in our application to handle sockets. At the moment of writing it, he defined an interface for the socket. He called it "Socket", no "I"s or "Interface" in it's name. Back then there was only one implementation to it "HttpSocket". It was great, it worked well. Today we needed to use our networking logic and communication modules over a UNIX socket. The solution was simple and done in just a few minutes. We created another implementation for "Socket" called "UnixSocket" and everything worked perfectly.

When we name interfaces we think about the clients, the other classes that are using our interfaces. In our networking module at some point we have something like "function writeToSocket(Socket $socket)". This is obvious. It looks great, it sounds logic and it is easy to understand. And one great thing there is that the client does not know that "Socket" is an interface.

Interfaces belong to the clients and not to their implementations; said Robert C. Martin and I totally agree. In the same way interfaces are like any other classes for the clients. What if you decide to change your interface into an abstract class. Very possible. After a few implementations you observe common code throught the implementations and extract it toward a Template Method design patter. Then... you have to change the name of your - now abstract class - interface into something else. An abstract class called "SocketInterface" has little sense.

And finally, a last thought, "Product" is a great name for an interface and it can be implemented by many many classes representing real-life products, for example "Keyboard" or "Mouse". However, there are some rare cases when you need an interface and you will have only one implementation. In those rare cases, I prefer to name well the interface and add "Impl" or "Implementation" to the the implementing class' name. This has more logic since the programmer writing the interface is most probably the one writing the implementation. However the programmer using the interface may be someone else from a totally different team or company or country. Why should that programmer of the client code know that "Product" is an interface or not. What if at the beginning it was a real object and the original programmer decided later that it should be an interface to better accommodate different implementations inside the "products" module? Why should the clients care? Why should they know?

If you are using a dynamically typed language, like PHP, there is almost no real reason for creating an interface that has only one implementation. Period. You have only one implementation and you are sure you need no other ones? Drop the interface.

Friday, November 8, 2013

Programmer's Diary: Just Good Enough


This is a repost from my old blog. Original post date June 8, 2013.

Some people are sloppy and they are doing too little. Others are perfectionists and they are doing too much. I think the best is to be somewhere in-between, to be just good enough and to create what is just enough. At least this is what I am trying to do each day.

But, doesn't "just good enough" means you are doing only the minimum necessary? Not at all. As any coach would say "it depends".

In most cases it takes the same energy to build something 80% perfect as it takes to build the remaining 20%. Closer you get to perfection harder it becomes to achieve advancement. I did no studies, it's just how I feel about what I do. Now, the question comes: "Is 80% good enough?" sometimes it is, sometimes it is not. If 80% satisfies 95% of the users of the product you are building, you did it. You may want to stop there and start a new product or a new feature. Let time and user feedbac guide you on the remaining 20%.

Other times 80% is not enough. If you build a car and you are unable to provide wheels, you are doomed. Nobody will buy your car. In that case you need some extra percents to achieve a minimum viable product.

The hardest thing is to find the 20% that is both difficult to create and also has little or no interest for the user. I have no recipe to solve the problem but frequent retrospectives on my own activity, feedback from others and some objective analyses can do miracles.

I am always trying to figure out where this good enough margin would be. Based on user feedback, or feedback from my colleagues, boss, wife, friends, etc I try to set for myself a little higher than expected targets both in my job and in my daily life. I always try to provide a little more and keep doing it in a consistent manner.

While this is mostly a good strategy I found that with higher quality comes higher expectations which in turn leads to even higher targets for my "good enough". And that's perfectly natural. What I find the hardest though is realizing when you are doing too much and have to take a step backward. Doing more and more each day will at some point hit your physical limits. When that happens you have to take a step back, take things easier for a while and adjust both your and your users expectations.

Only then, you can get back on track.

Thursday, November 7, 2013

Programmer's Diary: Usability Failure

This is a repost from my old blog. Original post date June 9, 2013.

My wife suggested to try and buy eggs from an egg dispenser (vending machine). Not exactly the model on the right, but something similar.

Even though we finally managed to buy the eggs, it was quite an interesting experience. First of all you start by pressing a button to rotate the internal shelfs so that what you want lines up with a sliding door. Each shelf has it's own door.

Than you have to put in the money. We first tried with a 10RON bill for a 3.5RON package. It just refused to take the bill. I can only presume that it had no way to give me the change and this was the reason for the refuse. However there was no indication of such a logic. And yes, I tried a couple different 10RON bills.

Then we went on and found 4 pieces of 1RON bills. After some trial and error it accepted all 4 of them. However I was required to try at least 10 times to insert them. Again, there was no feedback from the machine about the reason why it refused my bills.

Another problem was that there was no way to cancel the operation. So if I inserted 2 bills with success and then if it refused the other 2, I would have no way to get my money back.

Finally I had all my money inserted, a total of 4RON for a 3.5RON package. Now, there were about 10 shelfs with 10 doors. Only 1 or 2 doors actually had any products on them. The trick was that the machine had no idea about which shelfs are full and which one are empty. You had to open the proper door and only that. If you, by mistake, opened a door to an empty shelf, bye-bye money... At least there was a red text with an attention sign telling me this. But I totally think that the decision should be the machine's and not mine. If there is no product on a shelf, just don't let me open the door by mistake and loose my money.

I am wondering how many people can actually use this vending machine without falling in any of the above described usability traps? If you are a software developer or some kind of user interface designer, being it physical UI like a vending machine or a purely virtual one like an interactive web-page, keep in mind that we, the users, just want things to be done quickly and as painlessly as possible. Don't put traps and tricks in our way because we will not use your product the second time.


Tuesday, November 5, 2013

Programmer's Diary: Extract Variable NetBeans Macro

This is a repost from my old blog. Original post date June 14, 2013

I've got tired of manually extracting local variables so I wrote a little macro to do the job for me. Just copy-paste it into a new NetBeans macro, and add a shortcut to it.

Then, select the code you want to put into a variable, hit your shortcut and watch the magic happen.

---

cut-to-clipboard
split-line
caret-up caret-end-line insert-break
"$newVariable = " paste-from-clipboard ";"
caret-down caret-end-line "$newVariable"
caret-down caret-begin-line
selection-begin-line rem


---

Monday, November 4, 2013

I Just Visited the Most Unique Waterfall in the World



This is a repost from my old blog. Original post date August 26, 2013.

Last week I was watching the news on TV just to discover that according to THE WORLD GEOGRAPHY the most unique waterfall in the world is just about 150 km away from where I live. Being so close it would be a sin not to go and see it. So last Sunday my wife and I went on a drive to visit Bigar Cascade Waterfalls.


The largest city in it's vicinity is Timisoara, where I live. The waterfall itself is located near a small village called Bosovici, exactly on 45 Paralel. There are several ways to get from Timisoara to the Bigar Cascade Waterfalls.

  1. The shortest road - Timisoara - Moravita - Oravita - Bigar. It is the shortest road but unfortunately about 1/3 of it is in pretty bad shape. The road is all paved with asphalt, but about 50 km between Moravita and Oravita was repaired so many times that you will not be able to recognize the original layer. It will shake you quite hard. Even though you can go quite fast (80-100 km/h) it will not allow you to push as hard as you would like. The portion Timisoara - Moravita is in very good shape, but being a road that leads to the border with Serbia, it is quite heavily used and again you will find yourself blocked behind some slow car and you will not be able to go fast.
  2. The longest road - Timisoara - Recas - Lugoj - Resita - Anina - Bigar. It si about 30-35 km longer than the first option. It has very good road and asphalt quality. The only drawback with it is that Timisoara - Recas - Lugoj is one of the most heavily used roads in the country. So that 60 kms will be pretty uncomfortable to drive.
  3. The one I recommend - Timisoara - Buzias - Lugoj - Resita - Anina - Bigar. This is the one I recommend. Road and asphalt quality is very good. It is not heavily used so you will be able to drive at your own pace all the way to Bigar. It is about 20-25 kms longer than the first option but it is arguably the fastest way to get from Timisoara to the Bigar Cascade Waterfalls. It is also the most spectacular road. You start your trip on plain. Then you go through forests, then hills, then mountains and canyons. The most spectacular part is Anina - Bigar where you will be able savor abrupt serpentines on high altitudes in canyons and mountain forests.

But this should be a story about Bigar. Near the road, following some hand-painted road signs you will find a small waterfall hidden in a valley. The easiest way to recognize the entrance is the big 45 Parallel sign "Paralela 45", a big white road sign with blue letters. You will have to pay a visit tax of about 1 Eur for 2 persons (5 RON). A small bridge over the valley will lead you just above the waterfall to a tiny, beautiful miracle of nature.


On one side of this valley is the Bigar Cascade Waterfall in all of it's glory.


After you are tired of hiking on the rocks around the waterfall and taking pictures and admiring this wonder of nature you can get on a short trip (100m) in the forest to find the waterfall's water source.

 

Just follow the water and the path laid to you.

 

After a few minutes you will find the cleanest water you've ever seen. Just perfect for drinking as it surfaces between the rocks.


That's it folks. The Bigar Cascade Waterfalls and it's source.

If you have time and mood after visiting the Bigar Cascade Waterfall you can go and see some of the oldest water mills of these mountains located in and just after the village called Eftimie Murgu, 15 km distance from Bigar. There are 22 small mills, you can visit about 10 of them. It will take about 1-2 hours to walk near the river and find the mills, so be prepared for a long walk in a quite spectacular mountain landscape.

The mills are small, made of wood, and located in the valley created by the water.

They are all similar but slightly different. The most known characteristic of these mills are the horizontal wheels turned by the water.

 

So, if you happen to be in this part of Romania, the Bigar Cascade Waterfall and the water mills are certainly a great place to visit and spend a day in the mountains with spectacular panoramas.

And finally a little warning. Unfortunately we could not find a single decent place to eat. Nor near Bigar or in Bosovici or on the road. So be prepared with some food for the day when you live from Timisoara.

Friday, November 1, 2013

Programmer's Diary: Zombies and Phantoms

This morning when I checked our continuos integration system I spotted that our integration tests are running since a long time. This is unusual because they should finish in 3-4 minutes at most. After some investigation made together with a colleague of mine, we discovered there were about 2000 zombie processes on our build machine...

An hour before the end of this Friday working day I realised that after the changes we made lately to our software, the notification mails telling that a disk pool has been imported missed a key information: the pool's name! It seems like it turned into a phantom and vanished...

... after all, it's 1st of November.

Thursday, October 31, 2013

Let's Talk About Animals or Why Genders in Languages are Bad

My native language is Hungarian. It is one of those languages which are hard to pronounce but have an easy grammar. One of the particularities of the Hungarian language is the lack of genders.

However, I live in Romania. Romanian is one of the Latin languages like Italian, Spanish, French, etc. All these languages have something particular in common, the excessive use of genders.

Now, I am writing in English here, a language that found a quite unique and logical balance for use of genders. When you talk about a female person you use the female gender, when you talk about a man you use the male gender, for everything else (objects, animals, etc) there is a "neutral" gender.

English uses genders quite restrictively. There are no different versions of adjectives, substantives or verbs based on gender. So when you say "My dog is tired." it doesn't matter if it's a female dog or a male. If you say "My husband is tired."  you will use the word "tired" in the same way, regardless of the gender of the subject.

In Romanian, and most Latin languages, the problems are much worse ... so let's see how one has to reason when thinking about "My dog is tired.".
  1. First, one has to think if the gender of the dog can be determined or if it matters. If it does, the appropriate word for female/male dog will be used. The adjective "tired" will be also used in the appropriate form: "obosita" for female or "obosit" for male. 
  2. If the gender of the dog can not be determined, or it is not important in the context of the sentence, the "default gender for the animal dog" has to be used. The default gender for dog is male. But there is no rule for this like in English. It is just random and you have to remember it. Dogs are by default males, cats females, horses males again, chickens female, eagles male ... there is no rule. And some are actually neutral, yes there is a neutral gender also.
  3. However, determining the default gender and using the subject in the default gender also depends on the context. If you want to refer to a female dog attending it's puppies, you have to use the female substantive for dog "catea" instead of the male one "caine" and adjust you adjectives accordingly.
  4. To complicate things even further, if the number of substantives rises, for example we have "Two dogs are tired" we have to change our adjective for "tired" again, so that the plural and gender adjusted versions are used. Yes, each adjective has four versions just to accommodate this complexity.
I think my colleagues can understand why I sometimes can not make the proper connections in everyday speech. In Hungarian you have no genders. End of rent.

PS: In Romanian even objects have genders ... randomly assigned.

The New Place for My Ideas

Hello everyone. Unfortunately My Opera will be soon closed. Posts, articles and everything else will be moved over here in time.

Welcome.