Pages

Monday, September 30, 2013

Any unnecessary code is evil code

I bet you have already gone through a situation where you added lines of code just because it was easy enough or because you were already changing something on the same part of the program.

Well, don't.



No matter how easy it is to do something, no matter how fast, if you don't have a real - and good - reason to do it, don't.

Here are some questions you can ask yourself before implementing something, some that I keep asking myself all the time:

  • Does this add value to the product?

    Good code or features are the one that add value to the product as a whole. Just because a feature was well developed and works well doesn't mean that it adds value to the product.
    A feature that adds value to the product is something that the users also see as a value. How many times did you see a feature being added to the backlog, implemented and shipped just because your manager thought it was good, but after being shipped it ended up not being used at all?


  • Do the users really need this feature?

    Even if it does add value to the product, it may add little value to it. So the question is: do we really want to implement it?
    For example, to perform something the users have to click 5 times. You have the chance to reduce that from 5 clicks, to 3 clicks. But none of your users have ever complained about this, none of them have ever said anything about having to click too much to perform something. Do you really have to spend time improving that?


If the answer to both of the questions above is no, we can consider not implementing it.

But if after that you still want to implement it, ask yourself these two other questions:

  • What is the impact of this change, for your daily work?

    Always be very aware that even the smallest time you will spend on a change - even debating it - could be spent on a different matter. Even if you don't implement something you'll have to spend some time debating and agreeing on not doing so, and this takes time. Always remember that the time you spend on any feature could be spent on any other feature, one that adds more value to the product.


  • What bugs can this change generate?

    This is also a very important question. This is, in fact, what this post is all about. Giving a short answer to it: you may introduce a bug with code that you didn't need to write in the first place! Let's consider the example of the clicks again. What if, by reducing the number of clicks the user has to perform to achieve something, the programmer forgets to initialize something? That is awful from the user's point of view. The users had some process working with 5 clicks, and all of a sudden it got short - but it also doesn't work anymore. And guess what? He didn't request this change.


If you got bad answers for these questions, you will almost certainly not implement it all. And it's actually OK. It's all about delivering what adds value to the product, really.

Unnecessary code also goes into your ALM process, meaning you will also have to test it, write unit tests for it, and maintain it. All of these tasks take time from the programmers that could be working on something that really adds up to the product. Do you see the size of the problem work you have created, for something that will have no good response from your user base?

And don't forget that the next person who maintains these evil lines of code will spend some time trying to understand, and possibly fixing a bug or a unit test that was failing. All of that work for code that shouldn't have been added in the first place.

As I've said before: if you don't absolutely have to write code for something, don't.

Thursday, September 26, 2013

"But what if I had to test this?"

It's a fact that developing software using test driven development (TDD) techniques assures a higher quality than other conventional techniques.

TDD consists of making the developer start off with a test, and then write code to make the test pass, repeating this process in cycles. This makes us think about the best design for the smallest unit in code: methods.

Since you have to write the code that consumes your method before writing the actual method, you'll always end up with a simplistic, easy-to-use version of it. It's like putting ahead what you expect from your code, and then writing it. This often tends to push you to the best design: smaller, clearer methods with a single responsibility, fewer lines of code.

But forget about TDD for now, I'll blog about that later.


The message I'm trying to pass here is not "use TDD" or "write unit tests", but at least pretend that you're doing so! - By the way, you should totally experiment with TDD and PLEASE, DO WRITE UNIT TESTS!





But what if I had to test this?

Those of you who use TDD or just write unit tests will, eventually, change your design to make the testing easier.

But those of you who don't do any of them, you should.


Whenever writing a big fat method with lots and lots of lines of code, think about it. Ask yourself the question: "How would I test this?".


For example, take the following method:

public boolean DoSomething()
{
    var result = from child in this.Father.Children
                 from grandChild in child.GrandChildren
                 where (child.Foo == "Foo" &&
                       grandChild.Bar == "Bar" &&
                       child.Value > 10 &&
                       child.Value < 50 || 
                       grandChild.Amount * 100 < 0) ||
                       (child.Value > 100 &&
                       grandChild.Amount * 765 < 10000 &&
                       (child.Foo == "Not Foo" ||
                       ((int)grandChild.Amount ^ 2) == 3600))
                 group child by new { child.Foo, child.Value } into g
                 select new
                     {
                         Sum = g.Sum(child => child.Value),
                         FooMax = g.Max(child => child.Foo)
                     };

    var firstGroupedChild = result.First();

    if (firstGroupedChild.FooMax != "ZZZ")
    {               
        var correctedGrandChild = new GrandChild();

        correctedGrandChild.Bar = "Corrected grand child";
        correctedGrandChild.Amount += firstGroupedChild.Sum * 1.10;

        correctedGrandChild.InsertOnDatabase();

        DataAccessObject.DeleteFromDatabase(firstGroupedChild.FooMax);

        return true;
    }

    return false;
}
I couldn't even think of a bad name to that!


Now ask yourself: "How do I test this?".
A: Man, you're gonna have a bad time...

If the developer who wrote that code had the exact same question in mind from the very beginning, I'm pretty sure he would have dropped the idea of doing so much stuff - including a complex Linq query - on a single method just right there. Imagine how many Unit Tests you would have to write just to test the minimum of something like that. That is a terribly poorly written method.

If you don't test at all, it's actually acceptable to have something like this, given that you're not too worried about the quality of your product anyway. But you should! Do care about quality! Even if you don't assure it, at least remember that it exists!

Also, be a good guy and think about the fellow developer who maintains this code. He'll sure have a terrible time trying to find out just why the hell one of the "child" objects was not found on the first query, and not summed up.


Now imagine if we could translate the method above to the following:

var children = Father.GetChildrenThatSatisfySomeCondition();

var groupedResults = Child.GroupBySomeCondition(children);

var childFooMax = groupedResults.Max(child => child.Foo);

if (childFooMax.Foo!= "ZZZ")
{
    var correctedGrandChild = GrandChild.GetNewCorrectedFromChild(childFooMax);
    
    DataAccessObject.PerformChildCorrectionWithGrandChild(childFooMax, correctedGrandChild);

    return true;
}

return false;


Ooooooh! It all makes sense now! Now I can even understand the logic flow of the things I have to test! I could totally write Unit Tests for each one of the extracted methods now, because they all seem to be small, cohesive, and have a single responsibility.

And that would have been the first choice of design if the developer had thought about testing it before, or while he was writing it.


Code quality - and specially the semantics - matter, always.

Thursday, September 19, 2013

Calling methods on a caller Dynamics AX form

To call methods on a caller form from another form or a class for example, you have to fetch the caller from the args object, keep it as an Object and just then you can call methods in it.

You have to keep it as an Object like the caller method returns it to you, because then the compiler allows you to call methods in a dynamic way. This means that there will be no compile-time checking for the method that you are trying to call, as it happens with any object of type Object in AX, so if you try to call a method that doesn't exist on the form, you'll get a run-time error.


Here's some example code:

Object caller = _args.caller(); 

    // Or if you're in a form:
    // caller = element.args().caller();

    caller.someMethodOnTheForm();


And just to add some defensive code so that you can avoid getting a run-time error, you could add the following validations to the same piece of code:

Object caller = _args.caller();

    if (caller is FormRun && formHasMethod(caller, identifierStr(someMethodOnTheForm)))
    {
        caller.someMethodOnTheForm();
    }

Now you're also checking if the caller is in fact a form, and also if it has the method you're trying to call.

Monday, September 16, 2013

Changing Dynamics AX's forms' caption / text

Dynamics AX's forms' caption is composed of two parts: The name of the form / table being edited, and the primary key or at least two key fields that tell the user what record he has selected.

But do you know how to change these texts? I'll show you some ways of doing it in this post.

The first part of the caption, the name of the form, can be set on the Caption property, on the Design node of the form:



And that change can be seen on the left side of the form's caption:



Additionally, you can change the left part of the form through coding. Just add the following line on the init method or on whatever other key method you want it to be:

element.design().caption('Foo');

The second part, which is some information about the record, can be changed in two ways: through property settings, or through X++. I'll show both of them.

The table has two properties that you can use for this, the TitleField1 and TitleField2, under the Appearance node:



After setting them, you'll have to set another property on the form's Design node, the TitleDatasource, which should be the datasource related to your table:



And that's it, the value on the two fields you set on the TitleField1 and TitleField2 properties will be included on the form's caption:



And the last way to do it, through X++, is by overriding the caption method on the table. Of course that since we're changing something directly on the table, our change will reflect throughout the whole system. This means that if you change the caption of a table by overriding the caption method, you'll change the caption of all of the forms where that table was used as the form's caption.

We can do something simple, like this:

public str caption()
{
    str ret;

    ret = super();
    
    if (this.RecId)
    {
        ret = strFmt('Item number: %1, Total sold amount: %2', this.ItemId, this.getTotalSoldAmount());
    }

    return ret;
}

private real getTotalSoldAmount()
{
    return this.UnitPrice * this.SoldQuantity;
}


With the methods above defined on our example table, our form should look like this:



We only change the behavior if the record already exists on the database, by checking if it has a RecId set. We do that because we don't want to change the default text that appears on the form when the user is inserting a new record: