Day 7: Give Only One Responsibility to Each Class

Hi, this is the 7th part of  a series of posts on 30 tips to becoming a better developer. If you would like to keep up to date with the topics that I am covering, just check the main post.


One of the easiest ways to design software is to use the responsibility of each class as a guiding tool to improve your code. However, few people use this simple technique to create truly outstanding software.

The single responsibility principle (SRP) is a software development principle that states that each class should have one and only one major responsibility in the system. Any class with more than one major responsibility should be broken up into smaller classes (we can also merge together classes that do the same thing). Another definition, from Wikipedia:

“… the single responsibility principle states that every object should have a single responsibility, and that all its services should be narrowly aligned with that responsibility.”

Let us first understand why this works, and then how we can use the single responsibility principle (SRP) in practice.

Reasons Why the SRP works

The main reason is that giving a single responsibility for each class is just a compact way of describing object orientation. Let us try to describing object oriented code through the lights of the SRP:

  • Methods are associated to a class because they have something to do with that class. If a class has too many responsibilities, the methods there have no reason to exist inside the class. So, the idea that objects have associated methods makes sense only if the SRP is used.
  • Polymorphism is necessary because classes in the same hierarchy respond to messages in different ways. However, this is possible only if there is a standard set of messages that make sense for a class. The SRP says that each class in the hierarchy must have a single purpose, and this purpose is defined by how they answer to a specific message, by its polymorphism.

Moreover, giving a class a single responsibility is a great way of defining the scope of a class. Instead of piling methods together, you are just looking for a functionality set that go together well.

How to Apply the SRP in Practice

The easy answer for that is just: refactoring! First, go through your design and try to identify the responsibility of each class. The way I like to do this is to create a comment on the top of each class starting like this: “this class is responsible for …”

If you cannot state in a few words what the responsibility of the class is, then you are probably doing too much.

Another clue is given by abstract descriptions like: “this class is a manager for …”. Such descriptions hide the fact that a class has no focus. Try to give a better description of what this class does, or change it to improve its focus.

Further Reading

The single responsibility principle has been explained by many writers. Here are a few that I like:

[foto credit: http://www.flickr.com/photos/papalamour/2856099282/]

Using Default Values in C# 4.0

One of the new features of C# 4.0, the new version of C# included in Visual Studio 10 beta, is the use of default values.
If you are on the road long enough to be a C++ programmer, you will remember that default values was one of the features of member functions in C++. Quickly stated, a default value in a member function can be used to provide a value for an argument when it is not introduced by the calling code.
Having default values saves some time when writing code because you don’t need to type standard values for arguments that are rarely used.

Problems With Default Values

Default values, however, are not without their problems. First, the use of a default value can lead to confusion when creating methods. Suppose for example that you have two methods:

void f(int a, int b=0) { }
void f(int a) { }

This may trigger a compile time error, because there may be an ambiguity when using f with only one argument.
The worse problem in C++, however, is that the value of the constant (in this case 0) is not guaranteed to be the same between definitions of f in the base class and derived classes. This is a big problem that C++ users are still trying to solve today.

C# implementation

The advantage of C# in this issue is that, having a smaller compiler, they can make it much smarter. For example, the C# compiler will always give precedence to methods that have no default arguments, so there is less possibility for confusion.
Despite this, we should try to avoid default values in methods whenever possible. Default values can still make your code confusing and hard to maintain.
To avoid this kind of confusion, for example, you can try to get rid of methods with parameters that are used only some times. One way of doing this is creating separate methods for different cases. Also, you should give different names to methods. For example:

void FuncWithExtraArg(int a, int b) { }
void Func(int a) { }

is a better way to name the methods described above, so we don’t need to use a default argument.
Default arguments were added to C# to simplify coding for Excel and Word, where method have a lot of parameters of this kind. If you don’t need this feature, however, you probably should avoid default arguments altogether, and use them only when really necessary.

Day 6: Write a Tech Spec

Hi, this is the sixth part of  a series of posts on 30 tips to becoming a better developer. If you would like to keep up to date with the topics that I am covering, just check the main post.


Among all practices that could make you a better developer, perhaps one of the most overlooked is writing tech specs.

In my opinion, the reason for this is that many feel that, since writing tech specs are not coding, so it must be boring and useless.

Boring it may even be, but useless it is certainly not. The time you spend to write a good Tech Spec can be the most useful hour of your whole development effort.

What is a Tech Spec?

A Tech Spec is the lingo used in software development for a document describing the technical features of a piece of software you want to write. Most of the time, tech specs are written in boring language – the kind of stuff that only a boss will read when creating another report.

It doesn’t need to be like this though. Although most Tech Specs are created using highly technical language, you can create your own tech specs in a language that is easy for you to understand. And, in fact, this is the way that I recommend that things be done.

Here are some tips that I try to follow when creating my own tech specs:

  • Create your tech spec at a level of detail that you are comfortable with. Add examples, pictures, sample code, whatever makes the concept easier for you to grasp. Don’t try to start with something formal and bureaucratic – it usually doesn’t work well.
  • If your boss requires a formal tech spec, create one from your original, personal spec. It will be easier to do, and after you get practice on doing this kind of things, it takes only a few minutes.
  • Append your original spec as supporting documentation. You want your fellow developers (or yourself, later) to have access to your original ideas, which are certainly easier to understand.

What If You Don’t Have The Time?

You certainly do have the time. This is one of the things where you will end up spending more time if you don’t write a tech spec. So, the issue is that you don’t have the time NOT to write a tech spec before coding. It is like building a house without a blueprint: you can do it, but you shouldn’t.

How Can I Learn to Do This?

It really takes some time and experience, but here are some tips that I think can help:

  • Write down all the functionality that you want to implement (a good functional spec might be required for this step — more about this later);
  • Describe how each functionality can be implemented: the classes used, major algorithms, and/or databases. Also, provide a high-level overview of the functionality that will be implemented.
  • Give some idea of the time necessary to implement the functionality. This is an additional step that will help you a lot in determining the scope of what can be done.

Conclusion

Writing tech specs is not easy, but it can become natural if you practice. Moreover, if you find out how this works it can save lots of time for your and your team. I highly recommend starting with simple specs for small functionality, and then extend this to more parts of the system. In the end, it is all about planning before executing.

Go to the next post of the series:

Day 5: Write a Unit Test Before Coding

Hi, this is the fifth part of  a series of posts on 30 tips to becoming a better developer. If you would like to keep up to date with the topics that I am covering, just check the main post.


From all trends of software development in the last years, few are so important and useful as test-driven programming. Testing in general and unit testing in particular are an essential part of any software system and cannot be left to the last moments. In the past, testing was considered to be almost an afterthought. The idea was: to have a bug free system, build, then test. That was in the early days, when people believed in the waterfall model and in Santa Claus. Thankfully, experience has shown that nothing could be further from the truth. If testing is not added to the day-to-day of building the system it is really hard to make sure that final testing will work at all. Another way of viewing this issue is to understand that testing isn’t important only at a single moment in time. Instead, it is necessary during the whole process of creating software, the same way compiling is necessary at each iteration.

Unit Testing as “Extra Compilation”

keyboardThe workings of a compiler provide a good analogy for unit testing. Think of unit testing as an extension of compilation where you are testing for dynamic properties of your code, instead of static properties. For example, the compiler will easily check syntax errors and identify areas where you are using the wrong data types. Unit testing, on the other hand, will identify potential errors in the way you are implementing algorithms. The best thing of unit testing is that you are free to perform any test that can be possibly implemented in your programming language. Thus, you are not limited to checking for static properties, as your compiler is, but you can extend your checking to any dynamic property whatsoever.

What is the Catch?

Well, the catch, if you look at it in this way, is that you need to plan for testing. In reality, the main reason why it is difficult to test existing code is that it was not designed to be easy to test. Examples abound, like the common case where an object has concrete dependencies on many other objects, which creates a nightmare for someone who wants to test a class in isolation. There are several cases that can be considered when writing testable code, but the easiest way to solve these issues is to ask yourself before starting to code: how can I write a test for this functionality? Once you ask and answer this question, you will have everything you need to make unit tests that work and that are appropriate for the feature you want to implement.

Write a Test Before Coding

This can be summarized as saying that you should write a test for features you want to implement before writing the code. The reason is that if you are able to create a test for a feature, you will consequently implement it in a way that can be easily verified. And this happens just by the way you implemented the feature. Most people fail in this simple step and compromise all the time spent in coding. If you have to rework your code to test it, you might just as well be adding bugs that were not there before. So, adding unit tests after the case can, at least initially, damage something that was working fine.

Conclusion

Testing is good, and nowadays more and more people are aware of it. However, the catch is that you need to code with testing in mind, or you risk losing your time, instead of reaping more of the benefits. Writing tests before you code is a smart way of avoiding problems that might arise when creating unit tests.

Further Reading

  • Pragmatic Unit Testing, along with its sibling for C#, cover practically everything you need to understand about testing, including coupling issues, mocking objects, and more.
  • Test Driven Development teaches you how to develop based on tests. It is a great book with lots of examples for you to get used to this methodology.

Go to the next post of the series:

Day 4: Learn a New Programming Language

Hi, this is the forth part of  a series of posts on 30 tips to becoming a better developer. If you would like to keep up to date with the topics that I am covering, just check the main post.

Why Learning a New Programming Language?

Few habits maintained by a good developer can be as beneficial as learning a new programming language from time to time. The reasoning is simple: no language is perfect, and most languages have some useful feature or abstraction that may enrich your pallete of abstractions. Consider for example what happens when you are used to strongly typed languages, such as Java. You start your program design looking for what types would be necessary to implement the concepts you are trying to represent. While I am not saying that this is the wrong way to go, there are other options that you can take when working with other languages. For example, if you work on a functional language such as LISP, you will be more interested in designing a domain specific language (DSL) that can more easily represent your problem — and this might be an even easier and more productive way of looking at the problem. Different languages have different things to teach about how to approach problems. By learning different languages, you are learning different techniques that would be unnatural in your original language. For example, it is possible to write OO programs using plain C. However, as everyone writing interfaces in GTK+ knows, it may be a process that is a little cumbersome. Learning a new programming language may be just a simple way to try a concept that you want to use somewhere else. For example, you may want to understand how a dynamically typed language works, and use some of the concepts in Java using reflection, for example. The combinations of possibilities are endless, you just need to start searching around.

How to do it

There are several opinions on how to go about learning new programming languages. Some people think that you should try to learn a language that is very different from the one you are using. For example, if you are using VB, try Ocaml (that might be a little too much, but you get the idea). Another option, which I think is easier to implement, is to use your current knowledge as a leverage for learning other languages. In that case, if you start with VB.NET, you can next try C#, which uses the same library and concepts, so it is an easier jump. Then, you can try Java to learn at least a different environment. You can also learn new languages based on the task you want to perform. For example, if you need to create a new website, you might try Ruby and a framework such as RoR. If you are going to write an AI based application, LISP or Prolog might be good options. You just need to search around for people that are working on the problem you want to solve, and try to learn the language they are using. Whatever the way you do it, I think it is good to try. You can’t learn all computer languages that have been created, but the experience of trying to master some of them will make you a more flexible developer, that knows the tool to use for a given problem.

Further Reading

  • If you want at least to understand the differences between programming languages, the best thing is to take a general book on programming languages, such as Concepts of Programming Languages, By Robert Sebesta.

Go to the next post of the series: