Dmitry Nikolaev
Blog about software development
Friday, July 17, 2009
Why TDD ?
You understand why you happy with TDD when confidence about small part of just written code dissapear with red junit test.
Monday, June 8, 2009
Design must eliminate complexity
It is very common situation - when you find ways to start write your code. There are different design approaches you can use: top-down, bottom-up etc. But first of all you task when you start coding - resolve complexity. And you must understand that complexity may have a different face:
1. Algorithmic complexity
2. Interaction complexity
3. Organization complexity
Start from most important complexity, resolve it, and you win!
1. Algorithmic complexity
2. Interaction complexity
3. Organization complexity
Start from most important complexity, resolve it, and you win!
Thursday, June 4, 2009
PHP vs JAVA from developer perspective
Some peoples compares this technologies & languages by performance, server requiments, amount of needed knowledge.
But
Today I convinced that from developing good OOP software Java is the winner. There are many chained reasons for this, but the main are:
1. PHP weak supports for static typing.
PHP supports static typing only for stack calls:
function a (SomeClass $x, OtherClass $y)
You may say that PHP is _dinamic_ language. But tell me please, how would I know That some class A need instance of some class B if I not use type of variable ?
function a ($x, $y)
So, if you want use this function, you need know what types of parameter you must pass or you must go to source of this function and see what it does. If you make an error, nobody tell you about it. Dinamic typing ? Cool! But _I_ want to choose: use dinamic typing or not.
Now you can say: "PHP supports variables types in functions parameters". But most of all my parameters come to my constructor for setting up private class members. They cannot be typed!
class X {
var SomeType $x; // Error!
}
So, every time I use functions of my collaborators, I write:
$this->someInstance-> ...
and now my IDE dont suggest me function and, worst thing, IDE not tell me that something wrong if function name has error! Problem in IDE ? Seems that problem in PHP, because type or class member can be changed: PHP is dynamic language! WTF?
2. Refactoring
Rename/remove won't works in PHP. Because PHP has weak support of variable types.
Why only this things ?
Because this is matter most of all if you want achieve code which:
1. Reliable
2. Understandable
3. Reusalbe
But
Today I convinced that from developing good OOP software Java is the winner. There are many chained reasons for this, but the main are:
1. PHP weak supports for static typing.
PHP supports static typing only for stack calls:
function a (SomeClass $x, OtherClass $y)
You may say that PHP is _dinamic_ language. But tell me please, how would I know That some class A need instance of some class B if I not use type of variable ?
function a ($x, $y)
So, if you want use this function, you need know what types of parameter you must pass or you must go to source of this function and see what it does. If you make an error, nobody tell you about it. Dinamic typing ? Cool! But _I_ want to choose: use dinamic typing or not.
Now you can say: "PHP supports variables types in functions parameters". But most of all my parameters come to my constructor for setting up private class members. They cannot be typed!
class X {
var SomeType $x; // Error!
}
So, every time I use functions of my collaborators, I write:
$this->someInstance-> ...
and now my IDE dont suggest me function and, worst thing, IDE not tell me that something wrong if function name has error! Problem in IDE ? Seems that problem in PHP, because type or class member can be changed: PHP is dynamic language! WTF?
2. Refactoring
Rename/remove won't works in PHP. Because PHP has weak support of variable types.
Why only this things ?
Because this is matter most of all if you want achieve code which:
1. Reliable
2. Understandable
3. Reusalbe
Wednesday, May 27, 2009
Сatch your changes
It seems very obvious when you separate you code for design & testability purposes: SRP, business objects, factories, etc. Why we do that ? Because there are so many words ending with "bility": Testability, understandability, reusability...
And when you develop code You must keep in mind that maintainability also matters. It is good practice when you develop your test code first, but what about code that will be changed ? Maybe Refactoring help us? Sure, but you spend time refactoring not only code, but test too. That is not problem, unless your refactoring repeated so many times. The key problem in requiments that changed - pulling of all related code and tests.
What we should do to prevents our code and tests from requiments dependency? Seems that nothing. Every time when requiments changed we must change our code & tests. But maybe we can simplify our work? Yes, we can. And the key principle is: incapsulation of code that might be changed.
Ok, See example below:
We develop some widget, that has controls, and every time controls change they state, it sends request to server for some information update. What controls should we have? I dont know... Maybe TextBox & Slider? Lets write some test for it!
public void testThatWidget_Ugly_Works() {
/* This is example NOT about MVC */
Service myService = new FakeService();
TextBox nameTb = new TextBox("default");
Slider sizeSlider = new Slider(5);
MyWidget widget = new Widget(myService, nameTb, sizeSlider);
widget.onNameChanged("Adolf");
assertEquals(myService.getLastWidgetState(), new WidgetState("Adolf", 5));
}
Look nice, but do you see the problem? We mix too many things: we mix code with very different chance of modification. That is problem, because every time your requiments details changed, we _must_ refactor our tests. (And seems that we violate single responcibility principle, but main focus of this article - segregation of requiments that may be changed)
Separate yourself from redundant work:
public void testThatWidgetWorks_Fine_() {
Service myService = new FakeService();
MyWidget widget = new Widget(myService);
widget.updateState(new FakeWidgetState());
assertEquals(myService.getLastWidgetState(), new FakeWidgetState());
}
And when you develop code You must keep in mind that maintainability also matters. It is good practice when you develop your test code first, but what about code that will be changed ? Maybe Refactoring help us? Sure, but you spend time refactoring not only code, but test too. That is not problem, unless your refactoring repeated so many times. The key problem in requiments that changed - pulling of all related code and tests.
What we should do to prevents our code and tests from requiments dependency? Seems that nothing. Every time when requiments changed we must change our code & tests. But maybe we can simplify our work? Yes, we can. And the key principle is: incapsulation of code that might be changed.
Ok, See example below:
We develop some widget, that has controls, and every time controls change they state, it sends request to server for some information update. What controls should we have? I dont know... Maybe TextBox & Slider? Lets write some test for it!
public void testThatWidget_Ugly_Works() {
/* This is example NOT about MVC */
Service myService = new FakeService();
TextBox nameTb = new TextBox("default");
Slider sizeSlider = new Slider(5);
MyWidget widget = new Widget(myService, nameTb, sizeSlider);
widget.onNameChanged("Adolf");
assertEquals(myService.getLastWidgetState(), new WidgetState("Adolf", 5));
}
Look nice, but do you see the problem? We mix too many things: we mix code with very different chance of modification. That is problem, because every time your requiments details changed, we _must_ refactor our tests. (And seems that we violate single responcibility principle, but main focus of this article - segregation of requiments that may be changed)
Separate yourself from redundant work:
public void testThatWidgetWorks_Fine_() {
Service myService = new FakeService();
MyWidget widget = new Widget(myService);
widget.updateState(new FakeWidgetState());
assertEquals(myService.getLastWidgetState(), new FakeWidgetState());
}
The first test you must write in your mind when practice TDD
public class MyAppTest {
public void testApp() {
User = new User();
MyApp app = new App(user);
assertTrue(user.isSatisfied());
}
}
Sunday, February 1, 2009
Happy to announce: Mta
Happy to announce Magento translator assistant. This command-line program helps for crating more useful Magento translations easier & faster.
Project homepage: http://code.google.com/p/mta-project/
Project homepage: http://code.google.com/p/mta-project/
Subscribe to:
Posts (Atom)