Who We Are

Paweł Brodziński October 5, 2015

I face a number of occasions when I describe us as a company. A software development shop. A mobile and web development agency. A web development boutique. A product development services organization. I have used them all in every combination and more.

In fact, I struggle a bit when it comes to defining Lunar Logic’s identity through what we do for our clients. One way of looking at it is that we have software developers, graphic designers, testers, and product owners thus we help to turn ideas into software products. In fact, what our clients often stress is that we shine most when we get involved throughout the whole value stream of product building and not only take care of the software development.

Photo of the Lunar Team with the Lunar Logic logo

However, if you asked me what is our ultimate goal when working with our clients, I wouldn’t be talking about software development, UX or high quality. We do take care of all those, but they are just tools we use to reach our goal. That goal is to make our clients happy.

It just so happens that sometimes we make our clients happy by building software. That’s not always true, though.

I’m known to frequently advise our clients to send less work our way than they initially planned. I encourage them to cut down feature list. I propose simplifying initial solutions as much as reasonably possible. In short, I work hard for us to have less work than we could have otherwise.

Why? It’s because we don’t measure our success by how much software we built. We measure our success by how happy our clients were once our part was done. Strategies to optimize for that would mean adopting the ideas of Lean Startup, especially when it comes to rapid experimentation and validating business hypothesis relentlessly.

There’s more to it, though. When we start working with a new client there’s a lot of uncertainty about how the collaboration will look like. That’s why I often recommend a scope that’s even smaller than a Minimal Viable Product. Just a couple of weeks of working together can tell us a lot about how good and how effective our collaboration is. We call that idea the Minimal Indispensable Feature Set.

Then we can decide together whether we are on a good path towards our goal: making our client happy.

In theory, it may mean that we’ll end up doing just a couple weeks work instead of a much longer gig. That’s perfect. We don’t want to be busy all the time. That’s not our goal. Remember? We optimize our work toward clients’ happiness.

One could say that it doesn’t sound like the best strategy for an agency that basically makes money by selling its engineers’ time. Interestingly enough, the opposite seems to be true in our case.

As long as we succeed at keeping our clients happy we get more and more work from our existing and past clients. Referrals are a huge source of our new projects. Every now and then we need to reject new projects because we are fully booked.

The thing is that it’s hard to easily define who we are as a company. A software development shop that discourages their clients from building software. Well, that doesn’t sound usual.

Photo of of a few Lunar folks with the Lunar Logic logo

I think of us more as of a happiness delivery company. We deliver happiness. Normally by building software products. Sometimes by doing pretty much the opposite.

Whichever frame you want to use to describe what we do, either a web agency or software development professional services company, we are not your usual type. And we are vocal about that. The reason is some clients will love this kind of approach. Others will look for something different. Obviously we look for the former and we hope that you are one.

Barcelona: the capital of web development

Katarzyna Szawan September 16, 2015

When you look at the list of programming conferences, there is usually a clear distinction between the front and back-end oriented –  but it’s not the case with Full Stack Fest. Organised by Codegram, it merges 2 conferences: Barcelona Ruby Conference and FutureJS with a day of workshops and hackathon in between. This special event was the reason why Maciek and I visited beautiful Barcelona at the beginning of this month. For me, Full Stack Fest was the longest programming conference in my career, and I was really curious how it will be – conference time is usually really intense, and 5 days seems pretty much time.

Talks were very diverse and the schedule was well thought – there was a mixture of strongly technical talks, with lots of code examples and less technical talks, focusing either on soft skills, managing development process or other areas that could be inspiring for software developers. The conference’s schedule was divided into blocks of 2 talks. Between every block, there was a coffee break, breakfast or lunch – great opportunities to meet other participants. Apart from delicious food, there were plenty of coffee and drinks. Between the talks, Liz Abinante did a great job as a master of ceremony, providing necessary information and preparing the audience for talks. I really liked the sequence of talks – I think it helped to maintain a better level of overall focus by providing a variety of stimuli. The beauty and relaxed atmosphere of Barcelona helped us rest in the evenings so that the next day we could wake up ready to dive in the next portion of code.


The very first day of the conference was the most intense, but also the most interesting for me, so I decided to write about it in details.  It started as usual with a Ruby celebrity – Yukihiro Matsumoto, this time revealing ideas on Ruby 3.0. He shared a lot of inspiring thoughts – he is a language designer, and he encouraged all the programmers out there to be language designers as well (after all, in the process of writing code we encounter design issues). He also told about improving thread safety, a need for more abstract concurrency model, and presented stream model – you can take a look at the prototype here.

Barcelona streets. Photo by Maciek
Barcelona. Photo by Maciek

After a short break, we had Bryan Liles from Digital Ocean advising on the choice of development strategy. While comparing deployment environment, he used a metaphor of pets vs. cattle. Pet requires help when it gets ill, and there’s only one instance of it while cattle have many identical instances. If something goes wrong, they can be easily replaced. How to recognise the type of your current strategy? Well, if you need to ssh to your server to see logs, then you probably have a pet, not cattle. He also presented a couple of ways to make logs more accessible – mentioned https://getsentry.com/welcome/and http://prometheus.io/.

Then we had a pleasure  to listen to Eileen Uchitelle, who is a Rails contributor and shared with us her experience while trying to speed up Rails integration tests. She bravely took on the topic of measuring tests’ performance, which can be a difficult task – there is a number of benchmarks and profiling tools to choose from, but their output is usually difficult to read and compare. However, it’s worth trying – thanks to benchmarking we can investigate the most time-consuming parts of the code, and significantly improve overall performance. She showed us how to use these tools and recommended to do it in every project.

After lunch, there were two interesting talks focusing on the protocol and related issues. The first one was by Aaron Patterson, and apart from providing us with a serious dose of humor and photos of his gorgeous cats, he told us about Rails request and response lifecycle, what is wrong with it,  and how HTTP/2 could make it better. It introduces a lot of interesting concepts – for example, instead of 4 – 8 in HTTP/1, there’s only one connection – this way, we can track what has been pushed. And since we usually have plenty of assets in our apps and want a fast development environment, this sound promising. One concerning issue is the compatibility, as HTTP/2 is pretty revolutionary. The good news is that they’re planning to focus on backwards compatibility.

The other talk, presented by Aaron Quint focused on improving how the app communicates internally, and externally. The default choice for many developers is JSON, and in the beginning, it work very well indeed. It always starts small, but with time it’s becoming more and more complex and difficult to handle. He showed us a neat solution developed by Google – protocol Buffers described as language and platform-neutral extensible mechanism for serializing structured data. How does it work? You need to define the schema, a proto-format – it has explicit types and it deals with repeated fields, nested types and optional/required fields. It handles removal /addition of fields easily, but the output is not human readable. He also mentioned GRPC – a mobile and HTTP/2 first framework developed by Google using buffers – and TCPEZ – protocol and client-server implementation for a request/response TCP Server, where the client is the load balancer. The last solution has been in prod for 2 years already! The moral of the talk can be sum up in one sentence: don’t accept the community defaults without checking out the alternatives.

Another break, a bit of networking, and finally long awaited talk by Sandi Metz. She started with a little story about the past when she published the book which made her finally quit the job in order to teach people. He topic was  null object pattern, the active nothing. She described her approach to software development in four statements: infected by smalltalk (it was her day job for 12 years!), condition aversed, message-centric and abstraction seeking, then explained all of them in details. With more and more slides, she was revealing why using inheritance is not always a good idea and that it’s made for specialisation, not sharing code. She suggested making classes more alike, isolating the thing that varies and thus showed how composition and dependency injection are correct abstractions in this particular case.

The first day was closed with Rin Raeuber’s talk on the artificial intelligence and neural networks. She presented some basic ideas behind these terms, starting with biology, and then jumping to computer science perspective. She showed simple calculations and how learning with back propagation works – how we choose training data, adjusting weights etc. We also got to know what is the good use of neural networks – pattern recognition, filtering out the noise, signals processing.

The second day of Baruco was very interesting as well.  It started with a talk by Yehuda Katz showing how a naive Rust implementation of a Ruby gem beats the performance of a hand-tuned C version. Then we had Nell Shamrell talking about responsible refactoring – how to distinguish necessary changes from cosmetic ones, and how to evaluate the risk of starting a refactoring session. After the breakfast, we had an inspiring talk delivered by Ernie Miller about the history of building skyscrapers being a metaphor of software development.

Another talk presented by Piotr Solnica was about blending object-oriented and functional approaches. He started with describing his past – as many people from Ruby community, he started with PHP, found Ruby on Rails, and after initial enthusiasm realised it doesn’t work that well when the codebase grows. He told us about functional objects – immutable, having ‘call’ method and no side-effects. In his approach, immutability is a virtue – that’s why he advised to get rid of mutable objects – it is a mind shifting change, the objects must be ready as they can’t be changed later. Functional interfaces built as consistent and side-effectless are a great foundation for  higher level OO abstractions.

After the lunch, there was a talk with a live programming session introducing lambdas in Ruby by Corey Haines. Then we heard a talk by John Cinnamond inspired by Sandi Metz – extreme object-oriented Ruby and learned why we shouldn’t try to create pure OO languages. The last talk of Baruco was presented by Laureen Scott and it mixed programming with poetry. I had no idea they have so much in common! For example, there are some specific constraints in both, white space or a semicolon matters in these two things, it can change everything. Also, “say a lot with a little” applies to both fields.  


Both me and Maciek decided to attend React.js workshop, held by Erik Wendel and Kim Joar Bekkelund. It was a well prepared, interesting workshop, focusing on understanding the basic concepts of React, and how it really works. At first we got familiar with the theory behind React (they made a cool presentation, explaining it all!) and then jumped to practical challenges.  Starting with these small exercises made us better prepared for the actual task – creating a real-time monitoring app for Twitter. We didn’t have to bother with setting up the API access for Twitter or Google maps, and we could focus on getting to know React. Erik and Kim were really helpful and gave thorough, satisfactory explanations. If you want to start your own adventure with React.js, the instructions are public. Go and try it! 


FutureJS was even more diverse than Baruco. It was started by a great, informative talk by Rachel Adrew talking about the business of front end development. She started with going back to the beginning of her work, and describing how the web development was changing throughout the time. She expressed fear that due to our reliance of frameworks, we will stop pushing for better solutions. She stated that people should still value old-school fundamentals of web development – to be able to sit with a server and build a simple website. Let’s not become single tool experts! Rachel also presented her ideas on how should a web product be built – it should start with core experience to build progressively enhanced websites.

Functional programming was present in this part of the conference as well. At first, Massimiliano Mantione made an introduction to transducers – functions that take transformation and give another transformation. On the second day, Stefanie Schirmer gave a talk on the basic functional programming concepts, using cooking metaphors.

Ben Foxall during his talk. Photo by Maciek.
Ben Foxall during his talk. Photo by Maciek

There was one presentation which clearly stood out. Ben Foxall elaborated on the Internet of Things – he said that web browsers can do much more than just presenting the content. He presented a really impressive demo – an app which investigated various parameters of devices connected to the given URL  (battery level, location, device orientation, touch, light and other). Then, after determining the position of every device, he played a sound of singing birds on every device – suddenly, the conference room filled with sounds of the jungle!

Another very impressive talk was delivered by Steven Wittens. I think he presented the best maths visualisations I’ve ever seen – he focused on showing various image transformations (sampling, bilinear filter etc.) and different pixels representations. All presented on interactive, moving models, which brought a lot of applause.

Mikeal Rogers from Node.js Foundation spoke about developing Node.js, and what problems did they encounter while working on it. There is a huge ecosystem, but in 2014 they found themselves in a crisis, as there was no community focus on developing Node’s core, and no collaboration on standards.  He described their need to work out a better process, and that it should be participatory, efficient and transparent.

I must say that I’m a big fan of Baruco. Last year’s conference was awesome (see Tomek’s recap), and it was the same this year with Full Stack Fest. Again, chapeau bas to the organizers – I had an impression that they had a backup plan for every possible thing that could go wrong. They reacted quickly when one of the talks violated the code of conduct and did the same when live captioning problems arose – found an awesome replacement in no time (see this post). Thank you for a great conference, and see you next year!

A while ago I found great presentation on code refactoring called “All the little things” from Sandi Metz. The presentation was based on an exercise called The Gilded Rose Kata. It inspired me to play with the kata and here are some after thoughts. For those of you that like to get your hands dirty, I’ve also included a few code examples to help you get started with your own kata exercise.

What is the The Gilded Rose Kata?

Let me first start with explanation of what a code kata actually is. It’s an exercise which helps programmers improve their skills through practice and repetition.

The Gilded Rose Kata is all about two classes Item and GildedRose that you should refactor. Item has name, sell_in and quality attributes. GildedRose class has update_quality method responsible for decreasing sell_in and updating the quality attributes for each item.

The code is messy and has a lot of if statements that need to be resolved. Rules… hmm, they are pretty clear. Let’s get more familiar with them before we jump in any further.

The Gilded Rose Refactoring Kata

Here is the full description of The Gilded Rose Kata I found in Bobby Johnson’s repository:

Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system:

  • All items have a SellIn value which denotes the number of days we have to sell the item
  • All items have a Quality value which denotes how valuable the item is
  • At the end of each day our system lowers both values for every item

Pretty simple, right? Well this is where it gets interesting:

  • Once the sell by date has passed, Quality degrades twice as fast
  • The Quality of an item is never negative
  • “Aged Brie” actually increases in Quality the older it gets
  • The Quality of an item is never more than 50
  • “Sulfuras”, being a legendary item, never has to be sold or decreases in Quality
  • “Backstage passes”, like aged brie, increases in Quality as it’s SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert

We have recently signed a supplier of conjured items. This requires an update to our system:

  • “Conjured” items degrade in Quality twice as fast as normal items

Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn’t believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we’ll cover for you).

Just for clarification, an item can never have its Quality increase above 50, however “Sulfuras” is a legendary item and as such its Quality is 80 and it never alters.

Let’s play with The Gilded Rose Kata

I was looking for example in ruby and I found one in Emily Bache’s repository. Here is the code we need to refactor.

The first thing I had to do before rewriting the above code was to prepare a test suite to ensure my changes wouldn’t break the item rules. I simply added rspec and wrote the tests. There are plenty of them, if you want you can check out the specs here.

I was pretty sure every rule was covered in test suite so I made my first attempt to refactor the code. After I had done some work improving the code and I was still facing a green test suite a thought came to my mind.

Screenshot of green tests in the terminal

They call it Golden Master

We used to run dojo workshop at Lunar and we used a clever technique called Golden Master Testing to record the behaviour of the program. We recorded bunch of input examples and output results from the program we wanted to refactor. The recorded data was used to check if the refactored code behaves in the same way. It’s great when you have to deal with legacy code and you don’t have test suite. At least if you can prepare seed input for the program and collect outputs. I wrote script texttest_fixture.rb that creates all kinds of items and runs the update_quality method for a given number of days. Below you will find the output for 2 days.

$ ruby texttest_fixture.rb 2
-------- day 0 --------
name, sellIn, quality
+5 Dexterity Vest, 10, 20
Aged Brie, 2, 0
Elixir of the Mongoose, 5, 7
Sulfuras, Hand of Ragnaros, 0, 80
Sulfuras, Hand of Ragnaros, -1, 80
Backstage passes to a TAFKAL80ETC concert, 15, 20
Backstage passes to a TAFKAL80ETC concert, 10, 49
Backstage passes to a TAFKAL80ETC concert, 5, 49
-------- day 1 --------
name, sellIn, quality
+5 Dexterity Vest, 9, 19
Aged Brie, 1, 1
Elixir of the Mongoose, 4, 6
Sulfuras, Hand of Ragnaros, 0, 80
Sulfuras, Hand of Ragnaros, -1, 80
Backstage passes to a TAFKAL80ETC concert, 14, 21
Backstage passes to a TAFKAL80ETC concert, 9, 50
Backstage passes to a TAFKAL80ETC concert, 4, 50

Of course in our case more reasonable amount of days would be higher so we can cover more possible cases. I wrote a golded_master_spec.rb file that executes texttest_fixture.rb file for 100 days and generates nice readable it examples like below:

$ rspec spec/golden_master_spec.rb
Golden Master for GildedRose
match line 0: OMGHAI! should equal OMGHAI!
match line 1: -------- day 0 -------- should equal -------- day 0 --------
match line 2: name, sellIn, quality should equal name, sellIn, quality
match line 3: +5 Dexterity Vest, 10, 20 should equal +5 Dexterity Vest, 10, 20
match line 4: Aged Brie, 2, 0 should equal Aged Brie, 2, 0
match line 5: Elixir of the Mongoose, 5, 7 should equal Elixir of the Mongoose, 5, 7
match line 6: Sulfuras, Hand of Ragnaros, 0, 80 should equal Sulfuras, Hand of Ragnaros, 0, 80
match line 7: Sulfuras, Hand of Ragnaros, -1, 80 should equal Sulfuras, Hand of Ragnaros, -1, 80
match line 8: Backstage passes to a TAFKAL80ETC concert, 15, 20 should equal Backstage passes to a TAFKAL80ETC concert, 15, 20
match line 9: Backstage passes to a TAFKAL80ETC concert, 10, 49 should equal Backstage passes to a TAFKAL80ETC concert, 10, 49
match line 10: Backstage passes to a TAFKAL80ETC concert, 5, 49 should equal Backstage passes to a TAFKAL80ETC concert, 5, 49
match line 11: should equal

Golden Master to the rescue!

It turned out the golden master tests were failing on my refactored code. It means I made a mistake somewhere. My previously written specs were green but it seems like I didn’t cover everything. What was that? I checked the lines where the golden master tests were failing. I realized that I missed the case when an item with high quality=49 can’t reach quality greater than 50 but it should be able to reach a max quality of 50.

The rule for “Backstage passes” item says:

“Backstage passes”, like aged brie, increases in Quality as it’s SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert

I added missing tests to my rspec test suite and fixed the refactored code to make it pass.

What I’ve learned

Don’t trust myself too much. Don’t trust the tests I wrote. Always look for a way to prove if I’m wrong. The Golden Master Testing technique helped me with that.

What else have learned? There are plenty of little things pointed by Sandi Metz that helped me with refactoring code step by step.

  • Make smaller things – it’s obvious when you see so many if statements then you know it’s not good to leave them like that. They’re hard to read, hard to understand.
  • Duplication is far cheaper than the wrong abstraction – don’t be afraid to duplicate code. You are learning how to refactor the code and the abstraction is not yet clear until you understand exactly what your program does. Just don’t get stuck with wrong abstraction.
  • Keep SOLID principles in mind – we would like to have an easy way to add a new Item with different rules. It would be great to have the code open for extension in that case. And even better to have the code closed for modification at the same time so there won’t be the need to change existing code when adding a new item.
  • Things get worse always before they get better – intermediate steps during refactoring may look like they make things more complicated until you reach the point when you can get rid of complexity.

I did a second attempt to refactor code and I extracted a few smaller classes. I made the tests pass and I had a lot of fun with that.

Now it’s your turn

I prepared The Gilded Rose Kata repository with a ready to go test suite. If you want to tackle the exercise, you can clone it and switch to the “ready-to-start-exercise” branch .

$ git clone git@github.com:ArturT/GildedRose-Refactoring-Kata.git
$ cd GildedRose-Refactoring-Kata
$ git checkout ready-to-start-exercise
$ cd ruby
$ bundle install
# run tests prepared by me
$ rspec spec/gilded_rose_spec.rb
# run golden master tests
$ rspec spec/golden_master_spec.rb

This way you can run tests to ensure changes you make in the gilded_rose.rb file won’t break the test suite.

In the repository you will also find my first attempt and second with refactored code. Don’t open gilded_rose_refactored_1.rb and gilded_rose_refactored_2.rb unless you like spoilers!

All the little things

If you played with kata already then watch Sandi Metz’s video and check how she did the refactor. Hope you like it!

Oh, and by the way if you are interested what else I’m doing on daily basis you can check the knapsack gem and read more about it in my recent blog post.

Have you ever dreamt about a workplace, where your personality really matters? Where your sensitivity and honesty is treated as a primary value. Where being open and inquisitive is an important skill?

Welcome to Lunar Logic banner

Are you an awesome team player and love to spend time working with other people? And you are interested in User Experience and can easily fit into many roles.

Join us!

What we offer:

  • Support on your learning path
  • An unusual work environment with: kudos, badges, board games, etc.
  • A lot of fun Falling meteor
  • Paid

What we expect:

  • Passion for learning
  • Creativity
  • Critical thinking
  • Communication skills
  • Very good English

Apply for a QA internship »

Internships are planned for 3 months and are based in Krakow.

Open Salaries: How

Paweł Brodziński May 26, 2015

I guess the most interesting bit of our open salaries story is exactly how the change looked. I already mentioned that this was an important part of the preparation process, so it definitely wasn’t a gung-ho kind of thing.

First of all, open salaries was an opt-in program. No one was forced to join. Not joining would mean that others won’t know about that person’s salary and that person wouldn’t have access to the salary list.

The explanation is fairly simple. Everyone who joined Lunar was signing up to a company with non-transparent salaries. This might have been an important part of a deal for them. I didn’t want to force that change on anyone.

For anyone who joins the company after making salaries transparent, joining the open salaries program would be automatic.

One part is transparency, the other is having influence. The latter was much more difficult to design. Before the change pretty much no one had any experience deciding on salaries, so with no control raises could go through the roof. Well, theoretically at least.

Another, more important thing was that I wasn’t ready to give up full control. At the same time, giving up control eventually was the ultimate goal of the process.

We ended up designing three stages. The first one would be launched along with making salaries transparent. For the other two the trigger would be whenever we feel like we are ready.

During the first stage anyone who is in open salaries program can propose a raise for anybody, including themselves of course. This should be a concrete proposal; What kind of raise we are talking about exactly and why they think it is a good decision.

Everyone involved in open salaries is invited to share their opinion, either supportive or critical. Or propose a different solution, e.g. a different raise. The discussion happens in writing, in a shared document, so that we can refer to it later and can weigh in when we really thought it through. Finally, the decision is still made by me. The difference is that we have a very open and a very inclusive advisory process.

In fact, it is a variation of our decision making process.

The second stage will be different in a way that the decision would be made by the person who kicked off a discussion. There will be, however, overall financial constraints enforced by me. It would be in a form: “the budget for raises in the next quarter is no more than X.”

In the third stage we’ll remove the budgetary constraint. By that point it will purely be our decision making process.

Children in gnome hats happy about the orderly way in which they arranged their gems and coins

As I mentioned there’s no schedule for going through the stages. I even say that it is possible that the last one will never happen as we’ll never decide that we’re completely ready to remove all the constraints.

The crucial part of the process is a discussion. We didn’t choose to use an algorithm to decide who earns what. The reason is that I have yet to see an algorithm that  addresses what we value. Typically these algorithms would stress technical skills, experience, seniority, etc. We, on the other hand, pay a lot of attention to organizational culture, collaboration, and helping others to get better. It is difficult to quantify such things in a reasonable way.

We ultimately try to combine all our subjective opinions into an outcome that feels fair for everyone. Yes, that means that there are difficult discussions ahead. That’s why there’s one underlying principle for all the discussions: be respectful to everyone.

It is also an invitation for everyone to get involved. If someone is not happy with a proposal, and they don’t speak up, they can’t blame anyone else when a decision is finally made.

That’s pretty much it. One technical detail for launching open salaries was that opt-in decisions could be made for the whole day before the list was published. On one hand, it’s just convenience. On the other, it means that when open salaries are launched the list will be fairly full.

And of course even if someone decides not to join open salaries program at its kick-off they may join any time they want.

The whole plan was put into scrutiny of the whole company so that I could make corrections before launching it. There was nothing major that popped up though.