I am having a big argument with my colleagues on creating methods in classes rather than in Tables/Forms. I personnaly believe for a good ObjectOriented design most of the code should be written in classes rather than in Tables/Forms. Forms and Tables might be good for capturing events but not for including the business logic. I am totally in favour of writing as much code as possible in classes . My colleagues thinks otherwise . What do you guys think about it. Post as much arguments as you can. Cheers Amit Sood
well, as far as I remember, according to the Best Practice, data management code should be written on tables, while other login, long-time calculations, etc. should be moved to classes. Code on forms should be avioded where possible. But all this is for 3-tier environment. For 2-tier, I think it doesn’t really matter - the performance won’t improve, it’s just that this was it will be easier to read and find the needed code.
Totally agree with Kashperuk. Additionally, I think it also depent on who you are: Consultant or pure Developer. Consultant must work very fast and try to reuse evething. Developer can spent a little time for optimizing the code.
Hi Amit, Some reasons that I’m thinking about: By definition, the classes are specialized objects for colecting data from different sources (tables, forms), making operations with it, and eventually saving results in permanent storages (tables). The re-usability of code is a great advantage of classes. A single class hierarcy can be used for many similar goals by implementing specific code in the child classes and the keep the core in main class. The logic in main is available for children by calling super(), so there’s no need to re-implement. The class hierarcies allow overwriting and overloading; only in classes the definition of code can be guided by specific standards of accesibility and usability (eg abstract classes/methods, protected/public/private/final methods). If the logic is well structured and is placed in a class/class hierarcy rather than in a Form/Table it will be written once and available for many other forms/tables with minimum of customization. Classes can also be treated user defined data types, as they are temporarly holding values. They can be successfully used to pass complex parameters between other classes/forms, instead of using other temporary storages (containers, temp. tables etc.). Reasons: clarity, ease of handling. If the logic is simple, it can stay in the form. However there can be forms where things are complicated; it will need more than one class to structure the code in logical units (group methods/variables into specific classes). This will make easy to maintain for the further requests and also easy to understand by further developers. Rgds, Ciprian
Ciprian/Ivan/Khue thanks for your very interesting responses. Ciprian I agree with you on most of the things that you have written. Ivan your comment that “Data managment code should be written on tables” .Do you mean only the manipulation part like simple Insert,Find ,Delete,Lookup and updates etc if not i have a little differing opinion. In many places in AXAPTA i have noticed that lot of methods have beenn written on Tables and i have heard that MS is trying to change this by moving it as much possible to classes.I think this will make AXAPTA more robust maintainable and easy to debug. Cheers Amit Sood
I am studying…
It is an old post, but still valid to think on the basic concepts of the X++ language. To me, it feels that a difference has been created where this is not necessary. Tables should have been just classes with the option to override, extend implement interfaces. But in AX, the framework logic is here mixed with the business logic. As a result of this you see that e.g. client methods (jumpref , lookup) sometimes are found back on table level. Since that is the most central place, right …? But that should not be the case.
It would have been nicer if AX had just used the class concept for tables also and just make a couple of framework classes for the table specific things. Extending everything from ‘object’ would have been much clearer and extensible approach. What you e.g. now see is that tables can not have static members or members which are not persisted (only through methods). Once you need this, you must anyway wrap the table in a class …
I feel that when programming in AX, you should use the best practices from X++, but sometimes they conflict with other programming language best practices (C#, Java, C++).
I am really looking forward (sorry for this statement) to have the AX kernel being replaced by .Net Runtime. And the X++ framework being available in .Net. Then this will be fixed, I hope. Until that moment we need to use X++ best practices.
Things we will get then are good facilities for namespaces (prevent naming clashes), interfaces (identifying object responsibilities clearly), generics, etc.
There are some fundamental concepts here for designing AX customizations. I appreciate the idea that data level methods should be on the table. I compare these to stored procedures. These should not include direct business logic, but more along the line of filtering, formatting, and verifying data.
The class level is where business logic should reside. That is a VERY broad statement that covers a whole conundrum of possibilies. There are a lot of examples within the standard application, such as Accounts Recievable that show how to handle true cross-module implementations. Using inheritance and abstract base classes allows you to design customizations that are compatible across different modules. The layering should be most generic logic up to most specific logic in the inheritance chain. There’s also the concept of utility classes and factory classes. Design patterns are used throughout the standard app.
Forms should only contain UI logic. This should only determine what fields to show/hide and how to navigate forms based on workflows.
Of course, this is a high level overview of these concepts. I hope this helps.
Thanks,
Joel
Microsoft ISV Partner Manager
Hi Joel,
Interesting … i was used to work in an environment which was purely ‘collections’ based and fully object oriented. We did not have an option to fire sql queries at all. That was all hidden in the framework itself. In that environment the storage of the data also determined which class contained the business logic when the ‘data’ was brought alive (meta data in xml database …).
E.g. a select * from SalesTable was not possible, but you could ask car.getPassengers() and then you could get instances of different classes back (but still implementing the IPassenger interface …). So the logic that was implemented behind the step-in-the-car method could be different for different passengers (a women steps different into a car than a dog will do (sorry for the comparison). So they have different implementations.
How should I achieve this in your situation? When I do it in Axapta, i fire the query 'select Passengers from Car where carId = ‘xx’. That will return me all instances of a ‘record’. Should I wrap them myself in the specific passenger class to apply the right step-in method? or what is the approach here.
My assumption has always been: if the superclass has knowledge on its subclass that is always a design flaw. I also don’t know who my daughter is gonna marry in future … You often see this logic in axapta where a super class has a switch statement on which implementation is returned …
I am really looking forward to see your opinion on this.
Warm regards,
Dick
So your first question about where to put the Select statement. I would put that on the table as a getPassenger(Id) with exacly how you indicated it. I would have a passenger class. You can then inherit that class with passenger types. I have to say, though, that I COMPLETELY agree with your last statement about the subclass not knowing anything about the child classes. I have seen this all over the place in standard AX. In a lot of cases, the base class is used almost as a Factory class whether than a true parent class. This is what happens when you push business workflow into business objects.
There are defnitely options for following true patterns and practices, but when the standard application diverts, it forces you to follow unless you have the time to completely rewrite the standard functionality.
Joel
MS Evangelist
I’m an old dog in top down conventional programming, real OOP is very exciting (we OOPed in our own way to make the top down approach easier). The way I see it, cluttering a Class with methods that belong to a Table and a Form makes the Class clumsy and complex to be reused. I also agree with you to put the business logic in the Class but to an extend, only if the logic is applicable to a group, if not, move it down to Table/Form level, this will prevent the Class to become obsolete and ending up with hundreds of Classes or a few Classes that’s just about impossible to maintain.
thx All,
Just few comments …
I agree on most of the points. Just to share my thoughts i would like to make it bit more concrete through small samples …
-
in the framework … As an example: Having multiple documents (pdf, doc, xls, …) and each having a business class related, these classes (e.g. word document, excel sheet, pdf, xml, …) can be made searchable. But the search logic should not be part of the business object. It is a separate (search) framework responsibility. There will be a separate wordAnalyzer, pdfAnalyzer, etc.
-
Isolate logic in separate class and invoke through delegation call on object. It can of course happen that the logic to be invoked is generic to a group, but the responsibility can still belong to the object. In that case it is good to isolate logic, but still it can be invoked from the object itself. E.g. the price of a sales line, you will ask the sales line, but the call is delegated to a price list (priceProvider).
-
Isolate logic in separate class and invoke form outside object (subject). In case an inventory transaction is done, the sales order is really subject. So the information on the sales order is available but used from the inventory update context. The question is if this should be left to the sales order class, I feel, this should not be the case.
-
Keep logic in business object itself. The car.getPassengers() is really an association on the business logic layer and therefore it belongs there, I feel.
Ultimately, the table / class discussion is an AX discussion where a table is not a class (businessObject). In a couple other environments it is.And i also agree that you must follow the basic principles / best practices given for a certain framework (AX kernel). It does not make sense to fight against it. You need to keep ultimate goal in mind (satisfied customers against lowest possible costs ). And that can be achieved through a non-puristic, but just pragmatic approach.
That’s it for now … For me the most important thing on OO is : responsibilities … and that abstracts from table / class …
Good weekend!
hi Kashperuk
please just explain the
what is super () how is called parents class
hai ,
i open sales order details menu item in Accnts Recievable module.then it opens sales order form .in that i want to know which classes are hiting this form.
please reply me.
Hi subani,
if u want which classes are hitting u go menu item properties…in properties “menuitem type = action” means that is the classes…see “menuitemname = blabla…” that is the class name…go through and check…
Thanks,