Archive for the 'Visual Studio' Category

Red/Green/Refactor: a pattern for clean code that works, Part II (How, Where, When)

On the first part of this post I spoke of the concept of TDD, as well as the reasons for using it. But what about the way to apply it, and more importantly, the context in which it should be used? This second part will address those subjects.

Example: Visual Studio Unit Testing Framework

In order to exemplify a kind of unit tests used in TDD in a graphical way, I chose to develop a quite simple Tic-Tac-Toe solution in C#, using Visual Studio. The following image shows three tests for the Square class, which can hold only circles, crosses or empty spaces (simulating a Tic-Tac-Toe square).

image

The use of this unit testing framework (Visual Studio Unit Testing Framework) is quite self-explaining. There is a test class that holds tests methods, which can be executed individually or all together. Each test method shown here has an Assert method in the end, which is one way of defining if the method passes or fails.

Note that these tests were written before actually coding anything to the actual class; so, when going to code the required functions, the API has already been defined by the tests, and it’s quite easy to know what to do.

Another important thing to mention is that tests shouldn’t have any kind of correlativeness between each other, since they should act as individual testing units. Here this is exemplified by the fact that the instance of the Square class can have different names among the tests, and they’ll still work perfectly.

TDD, ATDD and Scrum

Since a key matter in TDD based projects is to know how to divide and prioritize development tasks, TDD is more effective in agile environments such as Scrum. Practicing TDD is a good way to deliver constantly (see Frequent Delivery in our company mindsets), so TDD and Scrum do benefit from each other.

Furthermore, mainly because of the last point in the benefits section of the first part of this post, it’s extremely important for the customer to have an active and appropriate role in constantly defining the direction of the project (he is the one that will consume the product, hence it is wise for him/her to participate in the decision making). So that’s where Acceptance Test Driven Development (ATDD) comes into consideration. ATDD is in fact a really interesting subject which deserves a post on its own and more, but just to mention the concept, it’s a methodology that implies writing Acceptance Tests, that become the criteria that the customer defines for his business requisites.

It’s important, though, that the role of the customer and the developer doesn’t overlap each other: in other words, the customer shouldn’t define specific implementation details (the how) as requirements, because the developer usually knows more about it; and the developer, on the other hand, shouldn’t decide on strategic external features (the what), since the customer knows more about his business.

(Ideas for this section have been taken from ‘Diseño Agil con TDD‘, a must-read free online book for Spanish-speaking developers interested on the subject)

Conclusion

Test Driven Development is a powerful methodology, that can bring outstanding results, especially in large, complex projects. Its benefits are best shown not when using it on isolation, but when combining it with the appropriate resources and organization.

Again, if you have any thoughts about what I’ve said, don’t hesitate to comment here.

Programming Practices for Self-learners

It’s a fact that lots of developers’ first steps with programming are self-learning, trial and error experiences. It’s not that I think it’s wrong; in fact, I myself followed that approach. But there are certain risks that come from learning to program on your own. This post will try to address them, and help those who are starting to program to follow the right direction.

Before going into to the actual recommendations, I should note that this post was inspired on reading ‘Microsoft Visual C# 2008, Step by Step‘, and so, some of the practices mentioned only apply to C# and similar languages. Nevertheless, I’m going to organize them from the general to the specific, so if you program in a different language, you can skip the specific parts; or, you could take this as a nice chance to learn some facts about these kind of languages.

A very common misconception many people have when they start programming is that the only necessary aspect of a program is that it functions. That’s wrong. In most real-case scenarios your program will not only have to work, but it will also have to be readable by other programmers, extensible in the future, and as efficient as it can be.

In this context, it’s advisable to follow certain guidelines about formatting and documenting:

  • Document your code. This as first may be seen as a waste of time, but you won’t think the same if you look at your code some months later. This is even more important if someone else will be reading your code. At least you should try to comment it.
  • Be consistent with formatting. Although it isn’t necessary to follow a specific formatting criteria, it does make a difference if you follow the same conventions all along your code. It makes it a lot more understandable.
  • Use descriptive names for identifiers. It’s wise to name a variable, method or whatever identifier you may use with a name that somehow reflects its function, so that it’s easier for you or other person to know why it’s there and what it does. Also, it’s not recommended to name two identifiers that differ only in case, because the resulting solution won’t be able to be reused in case insensitive languages.
  • Use an appropriate notation for identifiers. There are certain widespread notation conventions that most programmers share. It’s not that they are better. But everyone happens to use them, and so it constitutes a good way of making sure other people understand what you code. For example, in object oriented programming it’s common to use camelCase notation for private fields, and PascalCase for classes, public methods, and so forth.
  • Use parenthesis even if it isn’t strictly necessary. Even though it’s good to know the precedence, associativity and order of evaluation of operators, it’s better to write parenthesis anyway, not only to avoid mistakes, but also to make clear your intention when writing that operation to other people that may not be familiar with those rules.

Now shifting more into the concern of the actual functionality:

  • Separate the logic from the design. It’s a good practice to separate the actual business logic of your program from the user interface, so that modifying or even replacing one doesn’t alter the other. This also increments testability. An interesting way of putting this into practice is to follow an architectural pattern such as MVC.
  • Separate the functionality from error handling. While you can make a method output an error message directly to the same place it outputs normally, it’s better to separate the detection and signaling of an error from its catching and handling. Try()…Catch() and Throw() statements, present in lots of languages, are useful to this purpose.
  • Use object-oriented constructions in object-oriented languages. Most things you can do with objects and classes can be done with procedural constructions; but that ‘emulation’ of object functionality should be avoided, since object-oriented programming is a lot more efficient in this context (that is, the language was designed to be used like that). An example of this is to use global variables sparingly, when applicable.
  • Be aware of memory consumption. While this may seem irrelevant in small programs, it’s important to keep memory consumption into consideration. For example, if you’re going to use an integer variable that won’t reach higher values than 255, use the byte type instead of the int type. You never know whether your solution will be further extended or integrated into another one, and hence memory consumption should be always a concern. This should be paid more attention in languages without garbage collection.

Finally, some things about common operations you usually do:

  • Be aware of types. If, for example, you would make 5/2 (5 and 2 being int types) in a typed language such as C#, the result would be 2, and it won’t throw any kind of exception, because the result of an int divided by another int will necessarily be of int type. So you should be careful with this. Furthermore, even when it’s possible, try not to mix types For example, when making operations between an int and a double, it’s better to explicitly convert the int to double type so that both operands are of the same type.
  • Overflowing and checked statement. If you’re making integer calculations very close to overflowing the type’s limit, remember by default it won’t throw an exception, at least in C#. So it’s advisable to use the checked keyboard whenever the calculation could overflow; but don’t abuse of this, since it hinders performance.
  • Increment/decrement operators in postfix and prefix form. The increment (++) and decrement (–) operators can be placed both after and before the target variable; the difference is the result the expression evaluates to. For example, if you have a variable named ‘number’ whose value is 5, and you evaluate ++number, it will return 6, but if you evaluate number++, it will return 5 (even though the variable itself was incremented). When using these operators in isolation, however, it’s good to stick to the same way, to make your code clearer (that way is usually the postfix form).
  • Short-circuit. When you evaluate two expressions with the AND (&&) and OR (||) logic operators, you must be aware of a feature called short-circuit, that makes the program evaluate the second operand only if it’s necessary. That is, if you’re using an AND operator, and the first condition is false, then it’s not necessary to evaluate the second one to know that the whole expression will evaluate to false. In this context, it’s advisable to put heavy calculations, or expressions that are less likely to vary as the second operand, so as to save the program from making unnecessary calculations.

Another thing worth mentioning is that, although in most cases you can actually code with notepad, it’s more efficient to use a programming environment such as Visual Studio. It may seem that you “learn more” by doing everything by yourself, but in the end these programs simplify repetitive tasks and make you avoid extremely common mistakes, so you can focus on learning what you really must learn.

Following these practices probably won’t alter the global behavior of your program, especially if it’s not a large solution, but it’s definitely worth the time, since it’ll increase the overall quality of your programming, necessary in order to productively work in teams to develop large, significant solutions.

If you have any remark, suggestion, or if you want to share your experience on the subject, please don’t hesitate to write a comment, they are highly appreciated.