Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Friday, February 22, 2008

Thursday, February 21, 2008

TDD, Unit testing and legacy code

I was watching InfoQ video where Robert C. Martin and Jim Coplien talked about TDD, Design-by-contract, architecture and many other issues.

One of Bob's arguments was that

A test driven developer does not write a line of production code until he has written a failing unit test, and no production code can be written until there is a failing unit test.

it is irresponsible for a developer to ship a line of code he has not executed in a unit test.

I think that Bob's view on TDD and unit testing is a way too narrow. I'm slightly annoyed that people don't realize that the real value of TDD and unit testing will emerge weeks, months or years after the code has been written. Couple of months ago I read a Michael C. Feathers's book Working Effectively With Legacy Code. He says that

Legacy code is simply code without tests.

Big part of software development is to maintain existing applications and add new features into them. If that code does not have unit tests, it's legacy code. Even if it was written yesterday. TDD is a great way to prevent your code from changing into legacy code. When you are tweaking legacy code, you probably can't use TDD very effectively, but still you can and should try to get that code into a test harness. Why? The purpose of those tests is not TDD. The purpose is to create tests that verify current behavior and create a safety net for you. After your changes those tests should still pass. If they don't, you've broken something.

TDD implies tests, but tests don't imply TDD.

 

Technorati Tags: ,

Friday, January 11, 2008

Tuesday, December 18, 2007

Really nasty VisualStudio2008 RTM bug

From kb945425

Lines of code may be missing if you compile a solution that has a complex project structure in Microsoft Visual Studio 2008. The solution may incorrectly compile to Microsoft intermediate language (MSIL) code that omits certain method calls in the compiled .dll. This problem occurs when there are method calls to classes that participate in an inheritance hierarchy that uses generic constraints.

This is really scary. You don't event notice that your application does not do everything it is supposed to.

Kathleen Dollard found this bug.

 

Technorati Tags:

Friday, November 2, 2007

Active Record vs Objects

Robert C. Martin (Uncle Bob) wrote an interesting article about Active Record and objects. I do admit that he is partially right but I don't agree with him fully.

Martin Fowler's definition of Active Record is

An object that wraps a record in a database table or view, encapsulates the database access, and adds domain logic on that data.

Uncle Bob wrote

The problem is that Active Records are data structures. Putting business rule methods in them doesn’t turn them into true objects. In the end, the algorithms that employ Active Records are vulnerable to changes in schema, and changes in type. They are not immune to changes in type, the way algorithms that use objects are.

The fact that Active Record is based on database structures does not make it any less object-oriented. Active Record does not even try to solve the impedance mismatch between databases and objects. A full-blown ORM-tool should be able to solve the discrepancy. I don't see Active Record as an object-relational mapper at all. Ok, you can always say it's 1:1 mapper and it's hard to argue against that.

It has “hidden” data, and exposed behavior. I put the word “hidden” in quotes because the data is, in fact, not hidden. Almost all ActiveRecord derivatives export the database columns through accessors and mutators. Indeed, the Active Record is meant to be used like a data structure.

Active Record does not imply that data is exposed directly and this is the first time I've heard that AR is meant to be used like a data structure.  Most of the AR-frameworks just are a bit liberal on data visibility but so are also many ORM-tools.

Applications should be designed and structured around objects, not data structures. Those objects should expose business behaviors, and hide any vestige of the database. The fact that we have Employee tables in the database, does not mean that we must have Employee classes in the application proper. We may have Active Records that hold Employee rows in the database interface layer, but by the time that information gets to the application, it may be in very different kinds of objects. 

Active Record couples the object design to the database design. I don't see it as a problem. It's a design choice. In many cases it's totally acceptable approach. But if the business logic is complex or you want to use for example inheritance, the design gets messy quite soon. That will lead you to for example Data Mappers and full-blown ORM-tools. 

Tuesday, September 4, 2007

Thread Local: A Convenient Abomination.

A couple of weeks ago i tried to find a storage place for sessioncontext(s)  so that one WinForms application could have multiple sessions open at a time. I noticed that there are no easy solutions for that problem. Today i read an article that describes the other side of the coin.

Thirteen years ago, while working on my first book, Jim Coplien and I were having a debate on the nature of threads and objects. He made a clarifying statement that has stuck with me since. He said: “An object is an abstraction of function. A thread is an abstraction of schedule.”

It has become the norm, in Java applications, to assume that there is a one-to-one correspondence between a thread, and a unit-of-work. This appears to make sense since every Servlet request has it’s own particular thread. Framework authors have built on this assumption by putting unit-of-work related information (e.g. session) into ThreadLocal variables.

Clearly, the more ThreadLocal variables that hold unit-of-work related information, the more that the thread and the unit-of-work are related. While very convenient, the basic assumption is dead wrong.

It doesn't matter if you have 1 or 10 threads. The problem is always the same. UnitOfWork or SessionState should have a place that does not depend on threads. It's a dangerous assumption that UnitOfWork is directly related to one single thread. That assumption seriously limits your other architectural choices. 

So, though convenient, ThreadLocal variables confuse the issue of separating function from schedule. They tempt us to couple function and schedule together. This is unfortunate since the correspondence of function and schedule is weak and accidental.

What we’d really like is to be able to create UnitOfWorkLocal variables.

Couldn't agree more.

 

Technorati Tags:

Monday, February 12, 2007

The Tao of Programming

Ancient wisdoms.


A novice asked the Master: ``Here is a programmer that never designs, documents or tests his programs. Yet all who know him consider him one of the best programmers in the world. Why is this?''

The Master replies: ``That programmer has mastered the Tao. He has gone beyond the need for design; he does not become angry when the system crashes, but accepts the universe without concern. He has gone beyond the need for documentation; he no longer cares if anyone else sees his code. He has gone beyond the need for testing; each of his programs are perfect within themselves, serene and elegant, their purpose self-evident. Truly, he has entered the mystery of Tao.''