Showing posts with label quality. Show all posts
Showing posts with label quality. Show all posts

09 September 2013

Making code cleaner can result in a angry phone call


You have just released a update of your product. It includes more or less nothing, just a minor bug fix and cleaner code. Tomorrow it will reached 10 million smartphone users. The next day your phone is calling, one hour before it normally wakes you up. Its your boss!

I recently read a blog post by Erik Dietrich about legacy code (http://www.daedtech.com/intro-to-unit-testing-5-invading-legacy-code-in-the-name-of-testability) and how refactoring can help you to make it testable. The articel (and it’s serie) is very vell written, and as he writes in a comment he aims for novices. With this post I want to change focus from correctnes to performance.

Refactoring

In several books and blogs you can read about clean code, reduce cymclomatic complexity, duplicate code and how refactoring can help you. And that works!

If its legacy code there will most of the time be a comment saying something that it shall be done with caution and you have to write unit tests before. Thats also great!

But what you don’t read (or very rare) is that you should profile the code before and after to spot any performance differences. Why? Consider this:

What do you think happens if you refactor a code snippet, that is used in one of your most CPU intense part?

It will take longer time!

A quick person will say that he will inline that code, either by function of through compiler flag.

Well...that sound good, but are you allowed to change a compiler flag?

And if it’s already there, do you know how large functions that will be inlined? Maybe a software architecture has decided he wants to have control of what is allowed to inline for several causes. It could be: controling final binary size, debugging issues or something else.

Jumping around takes time

What happens when you have refactored a code snippet, is making a jump to another place and do something there. This jump takes time. If you need to bring some parameters to this function, you have to store them in a register. And also the return adress. This takes time. If you need variables in the refactored function, you need to allocate memory for those. This takes time. And you have to jump back when you are finnished. And this takes time.

This itself isn’t a problem, but if it’s done milions of time in a part that is already highly loaded, it can be a problem.

A angry phone call

Even if you as a developer thinks the code looks cleaner and is easier to understand, you also need to understand the harware and your customer. Here is some senarios:

  • There might be requirements about how long time a task can take.
  • There might be limitation on how much of the cpu can be used before a wathdog generates an alarm, or in worst case reboots your system.
  • There might be a customer starting asking questions why his system use more CPU load after your software update.


Learning to ride a bike is easy, the hard part is to ride in traffic jam

02 May 2013

How much shall I refactor?


"disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior"
-       Martin Fowler

Usually refactoring is initialized by code smell, a piece of code that does what I shall do, but doesn’t look “good”. But it can be initialized by several other reasons and some of them are:

Readability – a code part is really complex and the context it’s in would be easier to understand if it’s replaced with a function. For example, calculating the mean value of an array:

Testability – by replace some part of the code with a function, writing test gets so much easier to do. The code you want to test is depending on a previous part and you need to control the output from it.

Reusability – by extracting and generalize some part of the code, it can be re-used in several other parts.

So whats the point with this post? What I listed above is nothing new. It has been said and written of thousands of people.

A few days ago I watched a video from Öredev with Oren Eini, Hard Coding - A Design Approach. The most interesting he points out is that after Gang Of Four released  Design Patterns, we have refactored and abstract code into so many layers that the code gets more complex and difficult to understand. Without good documentation and/or someone describing to you what the code actually does, time-to-understand-was-this-code-does has increased.

I don’t say that Design Patterns are bad. I like them. I use them. I do believe that they should be used with caution.

Back to the first question, how much shall I refactor? 

As long as the code gets easier to read, test and modify, you should always consider refactoring, but check that your performance don't gets worse.


KISS – Keep It Simple, Stupid!

15 March 2013

Keep it small

It has been written about before. Its nothing new. Yet it is so difficult to keep the code small and I am talking about functions, files and modules.

Every day I see functions that are so large that its more or less impossible to understand what it does. Writing unit test takes more time than writing the acutal product code. Metrics like cyclomatic complexity and fan-in/fan-out is so high you get terrified. The code speak:

- Don’t touch me! You are on a mine field!

Why is it so hard to write good code?

We can’t blaim lack of tools because there are a dozens of the them out ther. Some of them are even free!

I belive its about people and culture. If you are working in a enviroment were people only focus on delivery, the quick and dirty solution will often be the way forward. And often it works fine. Its first when someone new looks at the code the problems gets visible. If same people work with the same code all the time, the problem gets hidden, because they have grown togehter with the code and knew the history behind every statement.

By writing small functions, your code gets easier to maintain, understand and modify.
By writing small functions, it gets easier to write tests, which is you saftey net tomorrow.
By writing small functions, its easier to reuse code and keeps the footprint smaller.
By writing small functions, the are less bugs and they are easier to find.

22 February 2013

Cache usage - Why do I have to care?

Last fall I held a internal course at my company with the title Coding with performance and quality in mind. In this post I will write about one part in that course, Cache usage, and I will try to answer the questions why do you have to care?

Some of you might say:
- Hey, you! This is nothing new. If I Google “memory cache performance” I get 55.800.000 hits.”
 Why another post?

Well, I will not write another post with lot of details. There are already lot of great post with it already (Google is your friend). I am writing this post for you who are a software developer but don’t know some much about hardware.



The big conclusion


You want the right data inside your cache at the right time!

- That sounds good!

But what is a cache?

In your computer, smartphone or some other device, you have main memory, normally called RAM, and you have cache which is a superfast memory. Some parts of the cache is located in the same chip as the CPU so it located really close to the CPU and makes the access quick (se figure below).




Details:  Cache can be divided in L1, L2 and L3 but also TLB, I - Cache and D- Cache (check the links in the end for geek info.

- Now I know what it is, but

How is it used?

Data that the CPU needs now or very soon is read from the main memory (or a cache further away) into the cache so it can be accessed really quickly. It takes longer time if the CPU needs to go all the way over the data bus and copy it every time before the CPU can use it. It might need it again very soon and therefore it is temporary stored in the cache.

But there are limitations! The cache is limited in size. For instance my Samsung Galaxy SIII has one L1 cache for data usage one for each core. Another limitation is that it can only copy chunks of data, cache lines, which typically has a size of 32, 64 and 128 bytes.

- So whats the problem? Just copy what you need!

Before the CPU starts copy data from the main memory to the cache, it first checks if it’s already exists in the cache. If it doesn’t, it is called cache miss and the CPU needs to work more, which you don’t wan’t.

- Ok, I understand what you mean. It’s good to have some understanding what limitations the hardware have, but

How do I minimize cache misses?

You organize your data after usage! Imagine you have a data struct ,as the one below, and you what to search for some persons id. The size of of one cache line is limited to 32 bytes.

struct person
{
 unsigned int id;
 char data[40];
 struct person *pNext;
}
...

while (ptr->id != magicId)
{
 ptr = ptr->pNext;
}


When the CPU copy one line, it will contain the id and a part of the first person due the the size of the cache line. If the first persons id doesn’t match, it will continue to search by updating the ptr pointer. The problem is that this information is not inside the cache. The CPU needs to copy that information from the main memory into the cache. This is a typically cache miss. A better solution would be to move the most common used data close to each other as below

struct person
{
 unsigned int id;
 struct person *pNext;
 char data[40];
}


- So you are saying that I shall re-organize all my data structs now?

No, first you analyse your code in a profiler and find your hot spots. Cache misses might not be your biggest problem but it’s good to understand if one of your loops turns to to be a hot spot.


24 January 2013

Software Quality - Knowledge of you current quality



In this post I will continue discuss what is needed before any actions can be taken to improvement and I will focus on knowledge of your current quality.

To receive this knowledge, data must be collected and analyzed, and it can be done in many different ways. I will discuss some of them here.

Collect data from users

Users are those how use your product in any phase, from using the actual code to end user of the final product.
  • What does the software developer think about the code? Is it easy to read? Is it easy to modify? And so on.
  • What do the testers think about the product?  What's their feeling? Is it well tested?
  • And finally, is the end user satisfied?

A story:
Once when I developed a user interface to a customer, I was really satisfied with it. You could almost do everything from one screen. The error handling was rock solid. The color contrast was chosen well. Then one day it was time to show it to the end user. We installed the product in the customer's vehicle and went out to the forest. The computer screen was shaking all the time during the demo and my choice of small buttons, edit fields and drop down boxes really sucked! There was no chance you could hit the right button.

So....what did I miss? I didn't know enough about the environment it should be used in (I had only tested it in a car that was parked outside the office). This was in my early career and the project was 100% waterfall. RUP was not yet hot (if it ever was)

Lesson learned: make sure you know your customer. Physical meetings/demo are extremely valuable.

Test results

How did the tests went? Was there lot of errors found? Test coverage, is it good enough? Was the test performed under good conditions or was the test phase decreased due to late deliveries? Any lose ends? 
This is a combination of measurable results (PASS and FAIL) and a feeling about the whole test scope.  Yes, I feel very comfortable with the test results or Well..we didn't had time to test this special case X, but it happens extremely rarely...


Metric results

Today, the range of tools to measure code quality are enormous, and it's more about taste and platform what is chosed. Some of them measures :

  • Static code analysis
  • Memory profiling
  • Cache misses
  • Cyclomatic complexity
  • Coupling
All these gives a indication about the none-functional quality and in some sense the functional quality. I want to point out that metrics needs to be put in context to be useful. A single “bad” value dosen’t says that the quality is low.

Summary

The end user might don't care if the code is extremely tight coupled, but it will effect him when he wants an update fast. The best knowledge of your current quality is received through gathering information from several sources continuously.

This was the last post about what is needed before any actions can be made for improvement. The next coming posts will be about what can we do to improve the quality.

21 January 2013

Software Quality - Interest of improvement

In previous post I discussed if it's possible to improve the quality and the conclusion was: it is, which is not surprising. I also divided software quality into two groups, functional and none-functional, to make software quality easier to reason about (which it isn't).

In this post  and the next I will discuss what is required to improve the quality and two parts that are necessary are:



  • interest of improvement
  • knowledge of you current quality


Interest of improvement

Before you can take any actions to improvement, there must exist a interest of improvement. Normally a company wants good quality on it's products so the customer are satisfied and continues to buy/recommend the product. You want:


  • the response time of your web browser to be than your competitors, else users will abandon you product.
  • to be able to test the product continuously in a reliable way to changes can be made earlier
  • the code to be clean and easy to work with, to make it possible to add new feature easier.

But all this will not happened by itself. It’s the people in your company that will make it happened. You need employee's that are like sports people that always seek ways to improvement. So how do you get them? Either you have been lucky with you recruitment or you have a company culture that endorse caring about quality and sharing knowledge. Geoff Schaadt has written an excellent post about How to make your employees care about quality. He writes:
how do you make your employees care about anything? You can’t make them.

It means that you can only create a culture that makes people care.

Different people
People are different and have different interest. We want people in our company and teams to be different, because it’s from their discussions innovations are started.
We want different people that are interested to learn more and a company that creates a caring culture.


In the next part I will continue with knowledge of your current quality.

16 January 2013

Software Quality - Can we improve it

Software Quality is something that everybody wants to be good. So what is good? And if it’s not good, how do we reach to that point? And if it is good, can it be any better?
Let’s start with some basics about software quality.


Basics

Software quality can be described as: how well we meet some requirements. It is often related to a business value. Is the customer satisfied with the product the paid for?
Customers are often people and what satisfies him will differ, therefore requirements for the product are well defined. The result is some form of minimum quality for the product that both the customer is satisfied with and the product developer can fulfill.

Requirements can be divided in two parts:
  • functional requirements 
  • non-functional requirements
Functional requirements refer to the specification, the requirements the customer and product developer has agreed to. They well defined. They can be measured and verified. If the quality is bad, the product developer won’t get paid.

Non-functional requirements refer to quality that is not directly visible to the customer, like maintainability and efficiency. Compared to functional requirements, these are “soft”. These are often results from architectural decisions and developers coding practices. Measurement of these requirements can be difficult and needs to put in context to give a meaningful value. 


What is good?

Back to the second question, what is good? Maybe it’s easier to define the opposite. If something is good, it can also be “non-good”. We can call it bad. If the quality is bad, it does not behave as we are expecting. The requirements are not fulfill. The customer is not satisfied.
If the requirements instead are fulfill, then the customer should be satisfied of the quality. We can then define that if we meet the quality for something we have agreed on then it is good! 

Let’s stop!

What about non-functional requirements? What if the code
  • has extremely long source code files
  • has functions that are pages long
  • is really hard to understand
  • only a part of it are covered with tests
  • is so tight coupled that even dynamite won’t separate it
  • needs extremely much memory and cpu
Can the customer be satisfied even if the internal structure is a mess?

Yes it can!

The solution can be to use more hardware or increase the development time with a factor X. It won’t be cheep but the customer will be satisfied. 

Or maybe there is another solution... 


If it’s not good, how do we reach to that point?

For functional requirements it’s easier to reach good quality because they have been agreed on with the customer. They are on paper. They can be measured. 
Non-functional requirements are more trickier because the limit for “good” is something we state our self. We don’t agree with the customer who the product shall look inside. It more about how much work are we willing to put down for a product?

If it's good, can it be any better?

I just claimed that the customer can be satisfied and the functional requirements are fulfill, even if the internal structure is a mess. He will probably not be overwhelmed. The good parts will weight more than the bad parts, as specified in the requirements.
But what if the internal structure (code) would be
  • easy to understand
  • easy to change
  • easy to test
  • cpu and memory efficient
It sounds nice. It sounds even better than good! No extra hardware needed. The development time is probably much lover. It open ups possibilities to change the requirements earlier in the development cycle if the customer is not satisfied. The staff are probably also happier because its more easier and more “fun” to work with the product. In the end the customer will be more than satisfied.

Can we improve it?

Back to the end question, software quality - can we improve it?

Yes we can! 

By having good quality on the internal structure the product cost will decrease and improvements of the functional requirements are easier to implement.