Showing posts with label Rant. Show all posts
Showing posts with label Rant. Show all posts

Friday, 27 June 2008

I hate TRANSFERFIELDS - Part II

I hate the TRANSFERFIELDS command. The last time I ranted about it I seemed to stir up some strong feelings, so I figured it’s time to bring this one up again.

Last time I commented on how the unsuspecting developer has no way of knowing what is going to happen when they use this command due to the way it copies fields between tables using the field ID to map the tables. Since then I have been tripped up again by this evil function and instead of simply moaning about it, I thought I would suggest an alternative.

So here I am going to introduce the all-new transferfields functionality. Microsoft, please feel free to take this idea and implement it in NAV.

The TRANSFERFIELDS command is programmed the same as now but in order to use it, a field mapping between the two tables must be defined at the table definition level. Let’s say we want to transfer fields from the Purchase Header table and the Purch. Inv. Header tables. You can find an example of this in the Purch.-Post codeunit as follows:
PurchInvHeader.TRANSFERFIELDS(PurchHeader);

This line takes the fields from the PurchHeader record variable and transfers the fields to the fields with the same field ID in the PurchInvHeader record variable.

If you have not defined a filed mapping between these two tables, the above code will not compile. In order to define the mapping I see it working like this.

Go to edit the Purchase Header table and select View menu and select the Table Mappings option. This will launch a form similar to the following:



On this form, you can insert a new line and enter the To Table ID to identify the table you want to map to. It would probably make sense at this stage for the system to automatically insert mapping between the two tables based upon the matching field IDs of the two tables. In this respect replicating the existing behavior would be pretty easy.

To customize the field mappings for the tables, the user will simply click the assist edit button on the Mapped Fields field and this will show the Field Mapping form.



Here the user can set up the field mapping. There are a couple of great things about this approach, you can ignore fields that you would never want to copy, such as the No. field. You can also map fields with different IDs. The other great thing is that field mappings can be managed by end users without the need to write code. An example would be if the user creates a new custom field on the Purch. Inv. Header table called Original Purchase Order No. The user can then make sure that the purchase order number ends up in this field by just using the mappings.

We could even add some rules on what to do when the fields don’t match in type, i.e. should we truncate the string or throw a run-time error.

Monday, 23 June 2008

Help!

In May I wrote a short piece for MSDynamicsWorld.com on on-line help and offered some thoughts on how it could be improved. In response to this article, I received a question asking how to configure the online help in Dynamics NAV.

In truth I have never done this. I knew I had read a document on how to do it but to be honest, it looked so hard I didn't bother. When I came to reply with the details, I really struggled to find the document I was looking for that described the help creation process. If you're looking for it, it's called NOHG.pdf

One of my points in the article is that we really need an easy-to-use help editor, similar to the one in Dyamics AX. Doh! I can't believe I just admitted something was better in AX!

Wednesday, 23 April 2008

Runtime Errors Suck!

I hate runtime errors. I think that functions in C/AL that can generate runtime errors should be deprecated where possible or altered in their function. Let me explain with an example.

Let's say you have two fields both called Description on two different tables. One of your tables is the Item table and the other is a new table called "New Item" (OK so I'm not going to win any prizes for imaginative table names in this example.) You want to make an assignment from one field value to another so you would do something like this:

l_NewItem.Description := l_Item.Description;


When your code runs the Description gets copied across and everyone's a happy bunny. But, let's say your customer says they want their item description to be made 20 characters bigger. What happens then?

Well let's assume that you increase the size of the Item Description field by 20 characters. Everything still works. Or so you think.

When NAV executes the line of code that previously worked fine on a record that has more characters in the new larger string than will fit in the other string, you (or more likely the first user that comes across that bit of functionality in your production system) will get a Runtime Error. Blurgghhh!

I have programmed in a few languages and C/AL is the only language I have ever come across that does this. What would other languages do? They would truncate the value and continue. They would assume, "hey, the programmer wants me to put a 50 character string in a 30 character string, he must know what he's doing, so I'll just give him as much as I can."

I like that, it's friendly, it makes me feel warm and fuzzy. Why can't C/AL do the same?

But there is a far worse function that can throw runtime errors and this should be banned altogether! TRANSFERFIELDS.

TRANSFERFIELDS is evil. It has to go.

What does it do? Well it, er, transfers, erm, fields (duh?) It is used to transfer fields from one table to another. Sounds cool doesn't it? How does it decide which fields should be copied? It uses the field ID.

What? The totally arbitrary field ID? Surely not, that would be crazy. Yup you heard it the field ID. NAV will attempt to make an assignment between two fields with the same ID, but different names and different types. And what do you think happens if the field types are incompatible?

Run Time Error.

The reason this function is evil is it lures the unsuspecting programmer into its little trap. It looks innocent. It looks like it may save you some time. Don't be lazy. Assign the fields one by one. Think about it, if you have 10 lines of code that assign each field from one table to another, anyone reading your code knows exactly what is happening. If you really want to be good, create a function on the table called CopyFromItem() or something similar. Then do the field assignments in the function so your code would look something like this:


l_NewItem.CopyFromItem(l_Item);


Now isn't that better?

So what prompted me to have this little rant? Well I am doing an upgrade from v3.70 to v5.00 at the moment and the damn thing just failed with a run time error. Some of the code in the standard upgrade toolkit gave me this error message:


The two fields below must have the same type:
Field: JobTaskNo <-- Table
Table: Temp Job Task Phase Step Comb. <-- Temp Phase Step Task Doc Line
Type: Code20 <-- Integer


Can you guess what caused this error?

TRANSFERFIELDS!

So if the expert coders at Microsoft get caught out, what chance do we have?