Pages

Monday, December 16, 2013

The Builder pattern

The builder pattern is an object construction pattern that is usually used to handle complex objects creation/initialization. A very good sign that it could be applied is when you start creating lots of constructors, or when your single constructors has lots of parameters, that is because you need the object to be constructed and returned in a state that you can actually use it.


The builder pattern also relies on constructing the object step-by-step, by method calls. Consider making a pizza for example. You first pour the tomato sauce on the dough, then you add cheese, pepperoni and olive oil. Then you bake it. Can you see the steps? If we were to create a pizza with a single constructor, we'd have something like this:

public Pizza(Dough dough, TomatoSauce sauce, Cheese cheese, Pepperoni pepperoni, OliveOil oil)

What if we'd actually want different toppings on the pizza? For example, instead of pepperoni, I'd like to have some sausage on top of the cheese, and I'm not a fan of olive oil. We'd then create another constructor overload for my pizza, right?

public Pizza(Dough dough, TomatoSauce sauce, Cheese cheese, Sausage sausage)

But now I want pepperoni, sausage AND some mushrooms! I think you can already see where this is going: we'd have a different constructor for each set of toppings we'd like on our pizza.

The pizza example is a classic one. With the builder pattern, using a builder object, I can make a pizza with as many toppings as I want! I can also chose whether I want olive oil on it or not.

We then have our pizza, which now has a list of toppings, instead of individual properties for each one of them:

public class Pizza
{
    public Pizza()
    {
        Toppings = new List<Topping>();            
    }

    public Dough Dough { get; set; }
    public TomatoSauce TomatoSauce { get; set; }
    public List<Topping> Toppings { get; set; }
    public bool HasOliveOil { get; set; }
}


Now we can easily implement our builder in a way that it'll be able to make whatever pizza we want:


public class PizzaBuilder
{
    private Pizza Pizza { get; set; }

    public PizzaBuilder()
    {
        Pizza = new Pizza();
    }

    public PizzaBuilder WithThinDough()
    {
        Pizza.Dough = new Dough { Type = DoughType.Thin };

        return this;
    }

    public PizzaBuilder WithThickDough()
    {
        Pizza.Dough = new Dough { Type = DoughType.Thick };

        return this;
    }

    public PizzaBuilder WithFlavoredTomatoSauce()
    {
        Pizza.TomatoSauce = new TomatoSauce { Type = TomatoSauceType.Flavored }; 

        return this;
    }

    public PizzaBuilder WithTomatoOnlyTomatoSauce()
    {
        Pizza.TomatoSauce = new TomatoSauce { Type = TomatoSauceType.TomatoOnly };

        return this;
    }

    public PizzaBuilder WithOliveOil()
    {
        Pizza.HasOliveOil = true;

        return this;
    }

    public PizzaBuilder WithTopping(Topping topping)
    {
        Pizza.Toppings.Add(topping);

        return this;
    }

    public Pizza Bake()
    {
        return Pizza;
    }
}


Notice that I left the whole responsibility of creating the tomato sauce and dough to the builder, as oppose to how I implemented how the toppings are added. I also created a property for the two first instead of creating sub-types for them. There's no real reason for this, they are just implementation details.


Just imagine now that for each one of the toppings we'd have a subclass. So we'd for example have a class called Sausage which extends the Topping class.

class Sausage : Topping
{
    // [...]
}

To get the toppings, I'll just create a class called Toppings which has a set of properties representing each one of the toppings. We could even apply the factory pattern in it.

After having all of these classes, we could then use the builder like this:

var pizzaBuilder = new PizzaBuilder();

var pizza = pizzaBuilder.WithThickDough()
                        .WithFlavoredTomatoSauce()
                        .WithTopping(Toppings.Mozzarella)
                        .WithTopping(Toppings.Sausage)
                        .WithTopping(Toppings.Onion)
                        .WithTopping(Toppings.Mushroom)
                        .WithOliveOil()
                        .Bake();


It's really easier to make pizza now, huh?

Now to forget about pizza and get back to our world, just imagine yourself building a complex XML document by taking advantage of the builder pattern. I bet it wouldn't be that much of a hard task.

Monday, November 11, 2013

Introduction to the SysOperation framework

I'll probably turn this into a series of posts, but for now, I'll just demonstrate the basics of the SysOperation framework.


The SysOperation Framework, initially called Business Operation Framework, seem to be the new substitute of the RunBase framework. As such, it allows you to perform operations that require parameters from the user, it allows you to set the operations to be executed in batch, or in a new asynchronous way, or in a synchronous manner. The great thing is that it simplifies the pack / unpack of variables that was pretty nasty in the RunBase framework, taking advantage of the Attributes feature, introduced with AX 2012.


So to get started, we must understand that the SysOperation framework works in a way that's close to the Model-View-Controller (MVC) pattern.
The key objects here are:

  • Data Contract:

    The data contract is the model class in which we define which attributes we need for our operation, commonly set as parameters by the user in a dialog. It's nothing more than a model class with a few attributes in it. We can define a SysOperation Data Contract class simply by adding the DataContractAttribute attribute to its declaraion. Additionally, if we want a set of methods to be available to us, we can also extend the SysOperationDataContractBase base class. With this class, we can define how our basic dialog will look like to the user. We can define labels, groups, sizes and types of the parameters.
  • UI Builder:

    The UI builder class is actually an optional class for the SysOperation framework, which kind of acts as the view part of the pattern. You should only use it if you want to add some extra behavior to the dialog that AX constructs dynamically for you. If you are perfectly happy with the dialog AX shows you when you run your operation, you shouldn't worry about this class. To create a UI Builder, you should extend the SysOperationAutomaticUIBuilder class. It will provide you a set of methods to work with the dialog's design, but we usually add extra behavior or customize a lookup inside the postBuild method.
  • Controller:

    The controller class has greater responsibility than the others. As the name suggests, it is the class that orchestrates the whole operation. The controller class also holds information about the operation, such as if it should show a progress form, if it should show the dialog, and its execution mode - asynchronous or not. To create a controller class you should extend the SysOperationServiceController, which will give you all of the methods you need.
  • Service:

    There are some who put the business logic on controller classes so that they also perform the operation itself. I'm particularly not a big fan of that, it's too much responsibility for a single class! The programmers who created the SysOperation framework probably think the same, and they have made a way to separate the operation. You can create a service class! The only thing you have to do is extend the SysOperationServiceBase class and you're good to go. This class is the one that should contain all the business logic. When constructing your controller, you will indicate which class holds the operation that the controller will trigger, I'll demonstrate it later.

So this was a brief explanation in my own words of how the SysOperation currently works. For more information, you can also download the official Microsoft whitepaper here.

Now on to the code.


SysOperating it


To define our Model, or our DataContract, all we have to do is create a class, with each of the values created as the class' fields, and parm methods, which will be our "properties". Each field that we want to pack and unpack during the execution of the operation has to have its parm method decorated with the DataMemberAttribute attribute. If we don't add that attribute, the value for that field won't be packed to the server, and will not be initialized when you try to access it on the service class. Additionally, parm methods without the attribute will not have its field displayed on the default dialog.

So for example, consider the following model class:

[DataContractAttribute]
class SysOperationDemoDataContract
{
    Name            name;
    BirthDate       birthDate;

    MonthsOfYear    monthThatWontBeSerialized;
}

[DataMemberAttribute]
public BirthDate parmBirthDate(BirthDate _birthDate = birthDate)
{
    birthDate = _birthDate;

    return birthDate;
}


[DataMemberAttribute]
public Name parmName(Name _name = name)
{
    name = _name;

    return name;
}

public MonthsOfYear parmMonthThatWontBeSerialized(MonthsOfYear _monthThatWontBeSerialized = monthThatWontBeSerialized)
{
    monthThatWontBeSerialized = _monthThatWontBeSerialized;

    return monthThatWontBeSerialized;
}

When we run a Controller that uses the above class as a DataContract, the following dialog is automatically constructed, without the fields that do not have the DataMemberAttribute. As you can see, our field monthThatWontBeSerialized wasn't even added to the dialog:




So after easily defining our model, which is a class that will store all of the values that we will need from the user - or not - for our operation, we can define our service.

To define our service class and have it called by the SysOperation framework, we must define a method that receives our data contract as a parameter. So for this demo, I have defined the following class:

class SysOperationDemoService extends SysOperationServiceBase
{
}

public str performDemo(SysOperationDemoDataContract _contract)
{
    str info = strFmt('%1 was born in %2', _contract.parmName(), _contract.parmBirthDate());

    info(info);

    return info;
}


It doesn't do much. It takes what the user has typed in the dialog and displays it on the Infolog. In a real scenario, this class could either contain the business logic itself, or just interact with other classes that contain it. I personally rather have the business logic in other classes, because by pattern, this class should always have the "Service" suffix. I'll talk more about naming conventions for the SysOperation later.

So we have our Model, we have our service. What about our controller?

The controller class has a few key methods like the RunBase framework, that you should be very familiar with, which are:

  • main
  • construct
  • new
  • validate
  • run


Their names are self explanatory, and if you are a little familiar with the RunBase framework you'll have no problem getting over them. I put the new method in that list because the new method of the base SysOperationServiceController class receives two strings as parameters, which are the name of the class and the method of the service to be executed. There is a neat method called initializeFromArgs which sets these values on the controller after it's constructed, given a correctly intialized Args object. This method allows you to use it with menu items, I'll blog about it later. Anyway, for this example we'll override the new method on our controller.

I've also put the construct method on the list. As a general good practice, your controller should have a public static method called construct, which will do all the dirty constructing (duuh) work. Additionally, you can override the new method and set it as a protected method, so that anyone who wants to use your controller will have to call the construct method.


So here's how I'll define our sample controller:

class SysOperationDemoController extends SysOperationServiceController
{
}

protected void new()
{
    // This tells the controller what method it should execute as the service. In this case, we'll run SysOperationDemoService.performDemo()
    super(classStr(SysOperationDemoService), methodStr(SysOperationDemoService, performDemo), SysOperationExecutionMode::Synchronous);
}

public static SysOperationDemoController construct()
{
    SysOperationDemoController      controller;

    controller = new SysOperationDemoController();

    controller.parmShowDialog(true); // Actually the default value
    controller.parmShowProgressForm(false);

    return controller;
}

public static void main(Args _args)
{
    SysOperationDemoController controller;

    controller = SysOperationDemoController::construct();

    controller.startOperation();
}

protected boolean validate()
{
    SysOperationDemoDataContract    contract;
    boolean                         ret = true;
    
    contract = this.getDataContractObject();
    
    if (contract.parmBirthDate() > DateTimeUtil::date(DateTimeUtil::addYears(DateTimeUtil::utcNow(), -18)))
    {
        // Failing the validate will not close the dialog, and the user will have another chance of inputting the correct values
        ret = checkFailed('The user is underage!');
    }
    
    return ret;
}

public void run()
{
    info('Run method has been called');
    
    super();
}

protected ClassDescription defaultCaption()
{
    // This will be the dialog's caption
    return 'SysOperation demo';
}

So as you can see we define which method will be executed as the service on the new method.
The construct method does the dirty work, setting some properties on the controller. The validate then checks if the user is at least 18 years old. If the validate fails, the user has another chance of setting the correct values on the dialog. Also, as a tip, I've set the dialog's caption by overriding the defaultCaption method. As for the run method, I've only overwritten it so that you can see the execution flow, which is:

>> main
>> construct
>> validate
>> run

Draw a sequence diagram in your head. :)


With the three classes that I have described here, you can actually run a simple SysOperation framework demo. You can do this by simply opening the controller class and pressing F5.


Here's some tips that can save you some time:

  • You should generate incremental IL for every change on any of the classes from the SysOperation framework. It won't take long, and unfortunately, it's necessary
  • When you start getting odd behaviors, specially when you change something on your DataContract and it doesn't reflect on your dialog, you should clean the usage cache. You can do this by clicking on Tools > Options > Usage data > Reset
  • You can debug SysOperation services if your Controller class' execution mode is either Synchronous or Asynchronous, when you've unchecked the option to execute business operations in CIL. You can get more info on executing business operations in CIL here.


As I've mentioned, the UI Builder class allows us to completely customize the dialog which is constructed for us. Since I'll probably turn this into a series of posts, I'll demonstrate this over the next posts.


Even though it's fairly easy and simple to understand, I must confess that I think it requires too much code infrastructure to perform some simple tasks. It feels strange having to write at least 3 classes to perform a simple delete operation that requires some extra logic or validation, for example. Still, I'd rather have to do so instead of having to control the dirty pack / unpack pattern of the RunBase framework.

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:

Friday, August 16, 2013

The str2num function and decimal numbers

There seems to be an issue with the str2num function when what you want is a real value. This matters because it can be used to convert from a string to an int or a real.

In order to successfully convert from a string representation of a decimal value to an actual real type on X++, you can't have any formats on your string. That means that the string has to be representing a double exactly as the real variable does: no thousand separator, and the dot ('.') character for the decimal separator.
It does not consider AX's region when performing the conversion.


Consider the following job:

static void Job1(Args _args)
{
    str val1, val2, val3, val4;
    real real1, real2, real3, real4;
    
    val1 = '100,000.000';
    val2 = '100.000,000';
    val3 = '100000,005';
    val4 = '100000.056405';        
    
    real1 = str2num(val1);
    real2 = str2num(val2);
    real3 = str2num(val3);
    real4 = str2num(val4);
        
    pause;
}

The only valid conversion is the last one, from the variable val4. The real variables have the following values after the assignment:



So just remember to be very careful when converting from a string representing a decimal value to a real X++ type when using the str2num function.

You can always use the .NET Framework instead. If you do, then you'll be able to set a specific culture when converting the double value, like the following valid X++ code:

System.Globalization.CultureInfo cultureInfo = System.Globalization.CultureInfo::CreateSpecificCulture("pt-Br");
    real parsedDouble = System.Double::Parse("1.200,99", cultureInfo);
    
    print parsedDouble;

Monday, August 12, 2013

Displaying a SysInfoAction button on the Infolog

Actioning it

Have you ever found yourself in a situation where the Infolog keeps throwing up the same error / warning at you and you have no idea how to resolve it?
For example: "The field Foo must be set to Y to perform this action". That's a pretty clear message: you just have to set the Foo field to Y and you're good to proceed with what you were doing, except that you have no idea where the Foo field is! When I started working with AX, I found myself in this situation more than I'd like to, and it always annoyed me to have to call someone and ask where the damn Foo field was.

But sometimes, the Infolog would show me a magic button that would take me exactly to wherever I had to go to fix the error it was showing me. That magic button is called a SysInfoAction. For the example I have given above, if the good guy programmer had put a SysInfoAction on the Infolog, you could just click on a button and a form with the Foo field would pop up.


So how do you do it? Well, there are some different SysInfoAction types. Just to list a few of them:

  • SysInfoAction_CostSheetValidate
  • SysInfoAction_Editor
  • SysInfoAction_Formrun
  • SysInfoAction_MenuFunction
  • SysInfoAction_newWindow
  • SysInfoAction_Properties
  • SysInfoAction_Showplan
  • SysInfoAction_TableField


As you'd expect, each one of these classes exposes a different behavior when the user interacts with the button on the Infolog.

Let's take a look at the SysInfoAction_MenuFunction for example.

It does what the name suggests: adds a menu item on the Infolog. And it can be of any type: Action, Display or Output.

Suppose we want to redirect the user to a form so that he can fill in the "Foo" field:

SysInfoAction_MenuFunction sysInfoAction;

sysInfoAction = SysInfoAction_MenuFunction::newMenuItem(menuitemDisplayStr(FooFormMenuItem), MenuItemType::Display);

warning('The field Foo must be set to Y to perform this action', '', sysInfoAction);

Just by creating that object and passing it to the warning() method, you made the user's life a lot easier. There's also a constructor available to the SysInfoAction_MenuFunction where you can pass in the control's name of the form you're opening, and the framework will set the focus to that control if it's found on the form. Although it helps even more, the call to the method should be ugly, and easy to break, since there is no compile-time checking if the control actually exists on the form.
The good part though is that if the control isn't found, it just doesn't do anything.

But what about security?

I have to say that the security framework team did a tremendous job overall, and it's just the same with the SysInfoAction feature.
The SysInfoAction, in this case, is nothing more than a menu item. Menu items are bound with security objects in various ways, so it's kind of easy to get the related roles or duties. That being said, guess what happens if the user doesn't have the permission to run the MenuItem you have added to the SysInfoAction? The user doesn't see the button.
So if you're worrying that you might accidentally redirect a user to an important parameters form which he shouldn't have access to, don't worry, because you wont: the security framework will take care of that for you.

That all being said, I'd advise to always use SysInfoActions where it really improves the user experience.

Wednesday, July 31, 2013

Boolean parameter VS exposing semantics

This can be a subject of quite long discussions with team mates during coffee hours.
Some team mates might think that simply putting a boolean parameter that slightly changes the behavior of a method is not a big deal. They may even make the parameter optional.

But when is that a good thing? When is it good to "just add a boolean parameter and make it optional"? Well, if it changes the method behavior in the smallest way possible, but even then it matters, then I'd say it's never good.

To prove it, consider the following two calls:

object.DoSomeLengthyWork();
object.DoSomeLengthyWork(true);

I don't know about you, but if I'm the one maintaining this code the first thing that would pop into my head when reading the second line would be "What the hell should be true?". The second thing I'd have to do would be lookup the method definition (or read its summary, if the developer who wrote the method cared enough to even create one), which is pretty easy, just position the cursor over it and press F12 right? Right! But what if that method is defined in another project / solution / dll that you do not have opened in your environment, or you don't even have access to?

And that, my friend, is why I strongly advise you to always go for the better semantics! Specially if you're writing public methods.

What I'm saying here doesn't make much sense if you work in a small company with a small codebase and maybe a team of 2 to 3 developers. But imagine working in a team of 20, 30 or 50 developers. Or even with a small codebase, imagine maintaining code that has been in production for 5 years or more, with no documentation whatsoever. Code whose owner or writer is not even working for the company anymore. I'm sure you'd have a blast trying to find out "what the hell should be true" in the example above.

Wouldn't it be easier if you could just have those two example lines written like this instead?

object.DoSomeSynchronousLengthyWork();
object.DoSomeAsynchronousLengthyWork();

"Ooooh, so that's what that true meant!"

And I won't even mention named arguments for cases like this, because they're pretty evil for distributed solutions. Jon Skeet has an awesome way of stating it, which can be found here and of course, in his book C# in Depth, that I quote:


The silent horror of changing names

In the past, parameter names haven’t mattered much if you’ve only been using C#. Other languages may have cared, but in C# the only times that parameter names were important were when you were looking at IntelliSense and when you were looking at the method code itself. Now, the parameter names of a method are effectively part of the API even if you’re only using C#. If you change them at a later date, code can break—anything that was using a named argument to refer to one of your parameters will fail to compile if you decide to change it. This may not be much of an issue if your code is only consumed by itself anyway, but if you’re writing a public API, be aware that changing a parameter name is a big deal. It always has been really, but if everything calling the code was written in C#, we’ve been able to ignore that until now.

Renaming parameters is bad; switching the names around is worse. That way the calling code may still compile, but with a different meaning. A particularly evil form of this is to override a method and switch the parameter names in the overridden version. The compiler will always look at the deepest override it knows about, based on the static type of the expression used as the target of the method call. You don’t want to get into a situation where calling the same method implementation with the same argument list results in different behavior based on the static type of a variable.


And that my friends, is why when it comes to boolean parameters VS method overloading, I always side with method overloading, that is, when the boolean parameter changes the method's behavior in a way that matters.

PS: C# in Depth is a great read, you should definitely read it.

Friday, July 5, 2013

Change CreatedDateTime field content

Since it's a table column controlled by the system, you can't update it. The same goes to the other system columns.

The compiler won't even let you write code like the following:

myTable.CreatedDateTime = DateTimeUtil::utcNow();

It'll spit out the error "The field must be a data element that allows assignment.".


However, there is a workaround to be done. The xRecord.overwriteSystemFields helps us with it. Its name is pretty straightforward. We should also grant the required permission to our code, by using the OverwriteSystemFieldsPermission permission class.

Here's how we should use it:

MyTableBuffer myTableBuffer;
    
    myTableBuffer = myTableBuffer::find();
    
    new OverwriteSystemfieldsPermission().assert();
    
    myTableBuffer.overwriteSystemfields(true);
    myTableBuffer.(fieldNum(MyTableBuffer, CreatedDateTime)) = DateTimeUtil::utcNow();
    
    myTableBuffer.insert()
    
    CodeAccessPermission::revertAssert();


There are two things to keep in mind:

  • This trick only works for insert operations. It will not work for update operations.
  • The OverwriteSystemFieldsPermission will only work for code running on the server.


To make your code run on the server, add the "server" keyworkd to its name, like this:

server public static void foo()

Just remember that the server keyword only works for static methods. In MSDN's words:

Establishes the location where the method is to be executed (on the server).
Can only be used on static methods. If the method is not static, you need to specify the location using the class property RunOn.

Thursday, July 4, 2013

Dynamics AX custom lookup in dialog

If you ever need to create a Dynamics AX dialog custom lookup, don't use the method naming approach, in which you name your method with a sufix like "_lookup". Your code will get very ugly, because the name of the fields in a dialog have very weak semantics. You'll most likely end up with methods like:

public void Fld1_1_lookup()

Instead use the new method introduced in Dynamics AX 2012, the DialogField.registerOverrideMethod method.


The method is very straightforward: you indicate what method you want to override, what is the method that overrides it, and in which form you want it to be overridden. Since it works with dialogs, you can use it on SysOperation UI Builders, on forms' dialogs and so on.

Because this method requires that the dialog is already constructed, you usually put it in "postRun" methods, like dialogPostRun or simply postRun, it depends on what you're doing. For SysOperationUIBuilders, you should call this method on the postBuild method.


For what I've seen and tested, the method that will receive the "event" we have overridden must always accept a first parameter of type FormControl, otherwise it just won't work.

Your method should look something like this:

private void lookup(FormControl _formControl)


Here's a full example of a lookup for a SysOperationUIBuilder, where we will override a lookup for a dialog field bound to the data contract:

  • Here we register the method that will be used to override the lookup method
    public void postRun()
    {
        DialogField           dlgFieldToBeOverridden;
        MyDataContract        dataContract;
        
        super();
    
        dataContract = this.getDataContractObject();
    
        dlgFieldToBeOverridden = this.bindInfo().getDialogField(dataContract, methodStr(MyDataContract, parmFieldToBeOverridden));
    
        dlgFieldToBeOverridden.registerOverrideMethod(methodStr(FormStringControl, lookup), methodStr(MyUIBuilderClass, myCustomLookup), this);
    }
    
  • And here's the method that will perform the actual lookup. For this particular example, we will assume we already have developed a new form called "MyLookupForm", and that we will be performing the lookup from a string control. You could use the SysTableLookup or the SysReferenceTableLookup approaches instead.
    private void myCustomLookup(FormControl _formControl)
    {
        Args                args            = new Args(formStr(MyLookupForm));
        FormStringControl   stringControl   = _formControl;
        FormRun             formRun;
    
        formRun = ClassFactory::formRunClassOnClient(args);
        formRun.init();
    
        stringControl.performFormLookup(formRun);
    }
    

Saturday, June 8, 2013

Execute Menu Items through code

I've seen some people trying to find out how to execute or run Menu Items programatically on the internet.

So I thought I'd best blog about it.

We have three types of Menu Items: Action, Output and Display.

An action is frequently a class that performs some business operation, an output is a report and a display is a form.

Menu Items are represented by the MenuFunction class. Here's some code example to run Menu Items through code:

MenuFunction menuFunction;

menuFunction = new MenuFunction(menuItemDisplayStr(MyDisplayMenuItem), MenuItemType::Display);
menuFunction.run();

Of course the code above may be changed to execute different kinds of Menu Items, for example, the code below runs an Output Menu Item:

MenuFunction menuFunction;

menuFunction = new MenuFunction(menuItemOutputStr(MyOutputMenuItem), MenuItemType::Output);
menuFunction.run();

And if you need to pass any arguments to the Menu Item you're trying to execute, you can pass it with an Args object. The run method accepts an Args parameter, like this:

Args args = new Args();

args.record(myArgumentRecord);

args.caller(this);

new MenuFunction(menuItemOutputStr(MyOutputMenuItem), MenuItemType::Output).run(args);

You should always use functions to get the name of the menu item instead of using a hardcoded string. This guarantees that if someone changes the name of the menu item, your code stops compiling and you have time to fix it before shipping it. The following are the three functions used to get the menu items' name. Their names are pretty straightforward:


Here's a link to a Stack Overflow question that I answered but didn't get the answer :(.

Friday, June 7, 2013

Dynamics AX Custom Reference Group Lookup

Microsoft Dynamics AX 2012 introduced a new form control type: the reference group.

And also, very often we'll have to customize the contents of the lookup, or filter them. We can do this by using the SysReferenceTableLookup class.


So go to your form's data source and find the reference field for which you want to perform the lookup. Override its lookupReference method.

The use of the SysReferenceTableLookup is very similar to the SysTableLookup: we construct a Query, add data sources and ranges to it, and then pass it to the SysReferenceTableLookup object, like the code below:


public Common lookupReference(FormReferenceControl _formReferenceControl)
{
    SysReferenceTableLookup     sysRefTableLookup;
    Query                       lookupQuery = new Query();
    QueryBuildDataSource        lookupQueryDataSource;

    // Construct the SysRefTableLookup object
    sysRefTableLookup = SysReferenceTableLookup::newParameters(tableNum(MyTable), _formReferenceControl)

    // Add the field list that will be displayed on the lookup form
    sysRefTableLookup.addLookupfield(fieldNum(MyTable, MyFirstField));
    sysRefTableLookup.addLookupfield(fieldNum(MyTable, MySecondField));

    // Construct the query's data source
    lookupQueryDataSource = lookupQuery.addDataSource(tableNum(MyTable));

    // Add ranges to the query data source
    lookupQueryDataSource.addRange(fieldNum(MyTable, MyFirstField)).value(queryValue('Foo'));
    lookupQueryDataSource.addRange(fieldNum(MyTable, MySecondField)).value(queryNotValue(''));

    // Pass the query to the lookup object
    sysRefTableLookup.parmQuery(lookupQuery);

    return sysRefTableLookup.performFormLookup();
}


Unlike the SysTableLookup, the SysReferenceTableLookup returns an object of type Common which is the record the user selected on the lookup.

For this example I created the lookup logic directly on the form, but you could always create a lookup method directly on your table, and then make the control's lookup method call the table one. It's entirely up to you.

Just don't forget to validate the user input, because filtering the lookup does not stop the user from typing in a value on the control instead of selecting the record on the lookup. You could do it by overriding the control's validate method or directly on the table with the validateField method.

Monday, June 3, 2013

Get selected records on the grid / datasource

This should also be a common task for Dynamics AX developers.

Fortunately, there's a little helper class in AX to make it easier for us, the MultiSelectionHelper.


For example, if you want to get a set of selected records in a grid, you could use it like this:

MyTableBuffer            myTableBuffer;
MultiSelectionHelper     selectionHelper = MultiSelectionHelper::construct();
Set                      selectedRecords = new Set(Types::Record);


selectionHelper.parmDataSource(myTableBuffer_DS);

myTableBuffer = selectionHelper.getFirst();

while (myTableBuffer)
{
    selectedRecords.add(myTableBuffer);

    myTableBuffer = selectionHelper.getNext();
}


The code above should be very useful when getting the list of selected records directly on the form, but if you want to get the selected records in a class that was called from a form, for example, you could use the MultiSelectionHelper like this:

public static void main(Args _args)
{    
    FormDataSource          formDataSource;    
    MyTableBuffer           myTableBuffer;
    FormRun                 caller = _args.caller();
    MultiSelectionHelper    helper = MultiSelectionHelper::createFromCaller(caller);
    Counter                 i;

    // First we need to get the correct form data source
    for (i = 1; i <= caller.dataSourceCount(); i++)
    {
        formDataSource = caller.dataSource(i);

        if (formDataSource.table() == tableNum(MyTableBuffer))
        {
            break;
        }
    }

    // We then tell the selection helper object to create ranges for the selected records
    helper.createQueryRanges(formDataSource.queryBuildDataSource(), fieldStr(MyTableBuffer, RecId));

    // Now we can traverse the selected records
    myTableBuffer = helper.getFirst();

    while (myTableBuffer)
    {
        info(myTableBuffer.RecId);

        myTableBuffer= helper.getNext();
    }
}
In the example above we received the caller form with the _args object. Then, we have to find the correct FormDataSource object. This should be the table for which we want to get the list of records. After getting the correct data source, we can then tell the selection helper object to create ranges for the selected records on the specified QueryBuildDataSource, which we can now get directly from the FormDataSource in Dynamics AX 2012, with the queryBuildDataSource method. And the last part is the same as the first code example, only this time I didn't add the selected records to a set, I just showed their RecId on the Infolog. Since we need to get the FormDataSource for this latter approach, we can only use it if our form only has one data source for the table we're trying to get.

This should be very useful when you need to perform certain action on a list of selected records. Hope it helps.

Tuesday, April 23, 2013

Getting the last error message from the Infolog

Even though you may think that you'll often have to do this, you won't. If you come to a situation where you'd consider doing this, you better think again, because there's always a workaround.

Still, if you really want to do this, you can do the following:


str errorMessage;

try
{
    throw error('Some error message being thrown here');
}
catch
{
    errorMessage = infolog.text(infologLine());
}

print errorMessage;

pause;

The infolog.text() method gets the text of the line number argumented. The infologLine() global method gets the total of lines in the Infolog. The code above always gets the last line added to the Infolog.


The code above will not hide the Infolog too. If you want to capture the last error message and then hide the infolog, or clear its contents, you can add a call to the infolog.clear() method right after you fetch the error message.


One thing to point out is that the infolog.text() method returns you the contents of the line number specified as text. This means it'll cast the line icon to a string too, making it become a tab character. You'll have to parse the returned string, because it'll be something like " Some error message being thrown here".

You can simply add a call to the strRem method to remove the tab character:

errorMessage = strRem(errorMessage, '\t');

Thursday, April 18, 2013

Be careful with Country Region Codes

When developing in X++, be careful when assigning some Extended Data Type to a table column, for example.

Extended Data Types have the Country Region Codes property, which, as the help text says, is a "Comma separated list of Country Region Codes where this can be shown".

This means that if you are working on a localization project for a Brazilian company for example, and you use an Extended Data Type which Region Code is "FR", for France, on a table column, that column won't be shown. Simple as that, it will not appear anywhere in any form.

You should always use the correct Country Region Code for your EDTs, depending on the country of the Legal Entity you're working with.

Monday, March 4, 2013

How to effectively refresh data on forms

Whenever you change some data in another process and you want to display it back on the form, you have to somehow refresh the values on the form.
On this post, I'll try to explain which methods we have to do that, and how and when to use them.


FormDataSource.refresh

The first method, available on the FormDataSource class, is the one that seems to be the most intuitive: the refresh method.

What it does is put the data stored in the form cache, for the current record on the controls. This means that it won't go all the way back to the database to ask it again for the record. In other words, data modified for that record on another process, outside of the form, won't be displayed since the cache won't be refreshed. If you need this, you can use the method below.

FormDataSource.research

The research method will do what the refresh won't do: it will ping the database and query it again with the form generated query. Because it does this, it will update all of the records on the data source.

There's also the optional parameter bool _retainPosition. When called with the argument true, it preserves the cursor position on the form's grid. This is very useful when you don't want the user to "lose" track of what he was doing, or to highlight whatever changed on the record.


FormDataSource.reread

This method is pretty straightforward: it simply rereads the current record on the data source. Also, this doesn't refresh any value that the user sees on the form. It only updates the record on the form data source level.

One common use of this method is to call the refresh method too right after.


FormDataSource.executeQuery

The executeQuery method also queries the database again and updates all of the records on the form data source. You should use this method whenever you modify the form's query, by adding a range or removing one, for example.


These are the ways of refreshing data in a form. And here's the post that helped me writing this one.

Tuesday, January 29, 2013

The Garbage Collector does not call the Dispose() method!

If you have ever wondered if the Garbage Collector calls the Dispose method on objects that implement the IDisposable interface, the answer is no.

It calls the Finalize method, which does nothing by default. If you have any unmanaged or additional resources that you want freed or released after the lifetime of an object, you must call the properly overriden Dispose method. I won't get in details on the Dispose pattern or anything like that, not on this post. Maybe on the future...

Anyway, this caught my attention because we had lots of objects that used unmanaged resources and they were not being freed, causing some memory leaks. The Dispose method was correctly implemented on these objects but the only thing is that it wasn't being called at all!

So my suggestion is that you always use try-catch-finally blocks or using blocks when dealing with disposable objects, specially when they use unmanaged resources. Make sure that you always call the Dispose method.

Simple example of a Foo class that uses some unmanaged resources inside of an using block, assuming that the Dispose method effectively frees any resources that the object uses:

using(var disposableFoo = new Foo())
{
    // Use your disposable foo
}

Tuesday, January 15, 2013

Ignore casing and diacritics on LINQ queries

When working with LINQ to objects, one could simply call methods to remove diacritics (accentuation) and ignore casing on LINQ queries. Since everything will run on .NET, the methods should resolve on the collections, and everything just works fine.

First of all, we'll need the following extension method:
public static string RemoveDiacritics(this String s)
{
    String normalizedString = s.Normalize(NormalizationForm.FormD);
    StringBuilder stringBuilder = new StringBuilder();

    for (int i = 0; i < normalizedString.Length; i++)
    {
        Char c = normalizedString[i];
        if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
            stringBuilder.Append(c);
    }
     return stringBuilder.ToString();
}
Now if you're working with LINQ to objects you could simply write LINQ queries like this:
var result = from p in People
             where p.Name.ToUpper().RemoveDiacritics().Contains(filter.ToUpper())
             select p;
But when you get to play with LINQ to SQL things get a little harder. LINQ to SQL will try to convert the query you've written into valid SQL statements, to run with SQL optimizations, on the database. It translates your query into SQL statements and executes them on the database. The result is then translated back into objects and sent back to your code so you can work with them. So when you work with LINQ to SQL, you either need to have a stored procedure declared on your database that the SQL statement generated can call, or you can "adjust" the database to your needs. I'd go with the second, by changing the column (or the entire table or database) collation, to one that ignores diacritics, or accentuation. For the above example, this could be done with the following statement:
ALTER TABLE People ALTER COLUMN Name [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AI
This should save you the trouble of developing a stored procedure to do that. Then, we could just use our filter in our queries:
var result = from p in People
             where p.Name == filter
             select p;
A question that I asked on StackOverflow motivated me to blog about this. It can be found here.