OOOERA - Forum - OpenEdge Architecture - Progress Community
 Forum

OOOERA

  • While I recognize that there were only 37 other people who attended the seminar this morning on OERA Update: Class-based Implementation and it will be about a week before the recording is posted ... and I don't know how many people will choose to sit through an hour and a half recording ... I would like to throw out some comments in reaction to this presentation for discussion.

    Naming standards

    We have talked about various options for naming standards before and, of course, there is always going to be a certain amount of personal preference involved here, and, yes, I recognize that any naming standard used in OERA whitepapers is just for the purpose of illustration and is in no way a model for a production system, but I see no reason that the naming conventions used can't be some flavor of one that would be "real world". Having things named things like samples.beCustomer just doesn't cut it when there is more than a handful of files. It really should be something like com.progress.autoedge.ar.customerBE instead, i.e., using the standard tla.domain.application.module structure and postfix type identifiers so that all files related to customer are grouped together visually. One can quibble about the details, but something like this would be a good example to get people thinking in the right direction.

    Singletons

    In the structure presented, there was a base class called ComponentBase which all components derived from and which included constructor code which used the object walking technique I described here http://www.oehive.org/PseudoSingleton to attach to a session services manager. Why not just New the session services manager and include this type of code in the structure I described to insure that this manager remains a singleton. Then, when the singleton keyword is implemented (bet you didn't know that it is already recognized) one can just change the one service manager class and everything else stays the same?

    PDS instead of entity objects

    Yes, I know that John is presenting this as an advantage of OOABL, but I think that if we are going to illustrate OO, we should actually do OO. Having include files to share dataset definitions between business entity objects and data access objects is very .p, if you know what I mean. The mis-named business entity object should be renamed into the manager or facade object it really is and we should get real entity objects created from the data access layer so that this complexity is actually encapsulated.

    Include files

    I really don't like having numerous include files and preprocessor definitions scattered all over my class files. Like I said, very .p.

    validateData()

    Why would a validateData() method not have a return type? What is it supposed to do when the data doesn't validate?

    Class files as first class citizens

    So, how long are we going to have to wait before we can instantiate a class file as the top level component, including on AppServer? No, defining .p facade procedures is not a positive feature. And, no, that doesn't mean that I am advocating locking down an AppServer or exposing inappropriate implementation details.

    getSIPath()

    OK, so we don't have abstract methods yet, but why define a nonsense method body that is always overridden instead of just putting this in an interface?

    templates vs generator

    I readily agree that there is a lot of repetitive code in an application, but I would much rather see PSC move in the direction of generating this code than using or advocating templates based on include files and preprocessor statements. Someone asked "Are there tools on the market which produce ABL out of UML?". The answer might be no today, but the tools and capability is certainly there and we could all benefit by exploiting that capability.

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • While I recognize that there were only 37 other

    people who attended the seminar this morning on OERA

    A practical issue: some people live in another timezone

    validateData()

    Why would a validateData() method not have a return

    type? What is it supposed to do when the data

    doesn't validate?

    What happens when you don't call it? Or will is be always called implicitly as well as a double check? How to avoid expensive operations?

    Class files as first class citizens

    So, how long are we going to have to wait before we

    can instantiate a class file as the top level

    component, including on AppServer?

    A stateless AppServer requires a non-persistent procedure call, so you won't get bound to a specific AppServer session. So I'm in favor of exposing the AppServer API as non persistent procedures... It's a facade you create, making you aware that you draw a line between the internal object model and the external one. You can always generate this layer by annotating your internal class methods.

    OK, so we don't have abstract methods yet, but why

    define a nonsense method body that is always

    overridden instead of just putting this in an

    interface?

    An interface means that you will have to implement the entire interface, while an abstract class gives you the luxury of having a base implementation.

    "Are there tools on the market which produce ABL out

    of UML?". The answer might be no today, but the

    tools and capability is certainly there and we could

    all benefit by exploiting that capability.

    You could use the Eclipse template based approach instead of includes.

  • This was

    an imitation of an abstract method, not an abstract class. E.g.,

    In order for this to be of any use whatsoever, it must be

    overridden in a subclass. My point is that it can be placed in an

    interface without the implementation details and that makes it

    cleaner. One can implement multiple interfaces, so in the worst

    case one could even put this method alone in its own interface.

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • Here is the link to where the recording will be posted, but it isn't there yet.

    http://www.psdn.com/library/entry.jspa?entryID=2233

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • ... I would like to

    throw out some comments in reaction to this

    presentation for discussion.

    Thomas, thanks for attending and for your feedback. A few responses...

    Naming standards

    ...

    Having things named

    things like samples.beCustomer just doesn't cut it

    when there is more than a handful of files. It

    really should be something like

    com.progress.autoedge.ar.customerBE instead, i.e.,

    using the standard tla.domain.application.module

    structure and postfix type identifiers

    This is a good point, and although as you point out, it's easy enough to set your own standards, our own examples can certainly move in a direction of a set of standards that will scale better than some that have been used.

    Singletons

    ... Why not just New the

    session services manager and include this type of

    code in the structure I described to insure that this

    manager remains a singleton. Then, when the

    singleton keyword is implemented (bet you didn't know

    that it is already recognized) one can just change

    the one service manager class and everything else

    stays the same?

    Creasting an instance of an intermediary class to do the work of locating or starting the "real" singleton class is an alternative to what was shown, but I'm not sure where the extra overhead of all of these intermediaries is justified. Whether the search is done in a super class, as shown, or delegated in some other way, or done as in your example by NEWing an intermediary, the result is pretty much the same, but as noted, the overhead of all of the intermediaries -- and of later passing all requests through this extra layer -- would concern me. BTW, the product group is of course always working on new features including extensions to our support for classes, but I would not bet at this time that the SINGLETON keyword per se will actually be used in the language; that may remain to be seen.

    PDS instead of entity objects

    Yes, I know that John is presenting this as an

    advantage of OOABL, but I think that if we are going

    to illustrate OO, we should actually do OO.

    But why? The whole thrust of the support for classes in ABL is to allow a mix-and-match not only of (as time goes on, mostly older) procedural code and (mostly newer) class-based code, but also to allow the same kind of relational definition and access to data while taking advantage of the useful practical feratures of classes (strong typing, etc.) I don't understand why "doing OO" per se is a goal. My goal was to illustrate the use of classes in ABL, not to illustrate OO for its own sake.

    Include files

    I really don't like having numerous include files and

    preprocessor definitions scattered all over my class

    files. Like I said, very .p.

    Well, I would share the goal of removing include files wherever possible. In this sample implementation, there are two principal ones: one is the dataset definition (and as shown, its constituent temp-tables in their own nested include files, if you want to break it up that way). This is used in two separate class hierarchies, one for the BE and one for the DAO; there could be other ways of doing this, so the DataSet definition would inherited by both sides and the include file wouldn't be needed. The other is the boilerplate code to support the individual Service Interface procedures. Since (in today's world, at least) this has to be a 'simple' .p (not a persistent procedure, not a class), putting the common code into an include file is -- as you say -- "very .p", but that's what the thing is. It could have been delegated out to in another running procedure or class, as an alternative, but in the sample it is in fact included in a procedure.

    Class files as first class citizens

    So, how long are we going to have to wait before we

    can instantiate a class file as the top level

    component, including on AppServer?

    I can't answer that, but I would still question whether that lack makes the sample shown an unattractive workaround as opposed to a perfectly reasonable solution. Given the basic facts that (a) you don't want to bind the AppServer session by instantiating either a persistent procedure or a class, and (b) that this top level of code on the server side needs to be able to invoke various standard support services, you don't really want the client invoking the real working classes on the server directly anyway. This is not to say that the lack of being able to NEW a class on the sever from the client, or run an entry point in an already running procedure or class, is not important to address in a future release of the product, but that doing this would still not become the norm in most Service Request operations of a well-constructed application.

    getSIPath()

    OK, so we don't have abstract methods yet, but why

    define a nonsense method body that is always

    overridden instead of just putting this in an

    interface?

    You still need an empty method body (or one that signals an error if it's actually run) to keep the compiler from complaining about the method reference in the super class with no definition.

    templates vs generator

    I readily agree that there is a lot of repetitive

    code in an application, but I would much rather see

    PSC move in the direction of generating this code...

    In 10.1B it is straightforward to extend OE Architect menus to invoke tools that can be written in ABL. It is also easy to tell the DataSet builder to export the data that results from building temp-tables and DataSets into a database rather than as XMI. Given this, it then becomes easy to write your own tools in ABL to generate all the standard components of an application from template files (using IMPOR, REPLACE, and PUT). A description of this is planned for the near future as a further set of samples and another paper for PSDN and -- time permitting -- as an extension to the presentation for Exchange. We (i.e, OpenEdge)are not likely to standardize on a single set of "official" templates because there are so many variants that people will want to have; given the raw data in a usable and familiar form, filling in templates from ABL is pretty trivial.

    Once again, thanks for your comments.

  • That would be appreciated ... it

    helps to set good examples at every opportunity. As to the

    singleton issue ... I suppose that if one is never going to

    implement the keyword which is already there, then it might be a

    moot point, but the attraction I see in the technique I used is

    that all components except the intended singleton can remain the

    same when the keyword is implemented and, in fact, however it is

    implemented as long as it is a property of the class. Yes, in your

    approach one just changes the base component class and recompiles

    and that is certainly better than an include or something, but it

    does mean that any impact analysis or whatever that one has is

    changed application wide. John, I think this is an area where we have very

    different opinions ... so I'm trying to advocate mine. It is

    obviously a good thing to allow people to mix and match, but you

    make it sound like a goal, i.e., the preferred target. In fact,

    your summary in the webinar seemed to be making that point

    explicitly that using this approach avoided the traditional OO

    coupling issues with the RDBMS. Obviously, you have a point and one

    can take that approach, but I think it is not as good an approach

    as using real entity objects because that is the way that one can

    encapsulate data and behavior in a single class. This also gets one

    away from this messy business of having to have include files

    references scattered around the application so that a common

    dataset definition can be shared. There is just no way I see this

    as good encapsulation. I am more than happy for you to write a

    whitepaper showing people who might like that sort of thing how

    they can mix and match ... it might be more comfortable for some

    people and it might help some to interface with the rest of their

    application. But, if we are looking to creating a model for a

    reference architecture, it shouldn't be that way. And, for the

    include files, it is really the same issue. It is poor

    encapsulation and there are better, more OO ways of accomplishing

    the purpose. On the issue of running classes instead of procedures,

    see my remarks above in response to Theo. I just see no reason why

    I can't start an application with a class and why I can't have

    facade classes on the AppServer. It is only a part of the problem,

    but it should be a trivial part of the problem. It should have been

    in 10.1B. Why can't you just define the method in an

    interface? I can't get very excited about writing code generators

    in ABL ... it is not one of the kinds of things that ABL is good

    at. I agree that one has to be cautious about having PSC come up

    with too much of the mechanism because it is unlikely that I'm

    going to like what you build, e.g., T4BL, BUT there is one big

    possible exception to this and that is if the mechanism is open and

    based on industry standards. In fact, this is a perfect opportunity

    for an open source project with PSC involvement, not POSSE like,

    but something which actually belongs to the community. Frankly, I

    can't see why the technology should be anything other than MDA

    because that would allow us to leverage off of existing tools like

    EA. PSC could help get this started and then let the community take

    it where the community wanted. It might well result in multiple

    flavors and branches, but what's wrong with that?

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • On the issue of running classes instead of

    procedures, see my remarks above in response to Theo.

    I just see no reason why I can't start an

    application with a class and why I can't have facade

    classes on the AppServer. It is only a part of the

    problem, but it should be a trivial part of the

    problem. It should have been in 10.1B.

    Being able to execute a static class method on the AppServer might be a reasonable option, but is this really any different than executing a non persistent .p? But remotely instantiating a class instance and in the next roundtrip invoke a method on it, doesn't sound like a good idea, since the AppServer has to manage the lifetime of the instantiated object. It's similar to launching a persistent procedure and invoking internal methods on it. It means you will be bound to the AppServer.

    But maybe you're concerned about the fact that OOABL'ers have to learn about OOABL and procedural programming when they want to do something with the AppServer. Here I would say that tooling is the answer: the proxygen tool could generate the .p wrapper (stubs) for you as well as the client side proxies.

  • Creasting an instance of an intermediary class to do

    the work of locating or starting the "real" singleton

    class is an alternative to what was shown, but I'm

    not sure where the extra overhead of all of these

    intermediaries is justified.

    That was my response to Thomas as well in "the war against shared variables"-discussion http://www.psdn.com/library/thread.jspa?messageID=7250᱒. Especially since there is no garbage collection in the OOABL, so you have to construct and desctruct the classes yourself, which makes it very easy to leak memory.

  • Include files

    I really don't like having numerous include files

    and

    preprocessor definitions scattered all over my

    class

    files. Like I said, very .p.

    Well, I would share the goal of removing include

    files wherever possible. In this sample

    implementation, there are two principal ones: one is

    the dataset definition (and as shown, its constituent

    temp-tables in their own nested include files, if you

    want to break it up that way).

    The issue here basically is: to create entity classes that encapsulate data (buffers & temp-tables) and that expose them as properties or to pass temp-tables around explicitly (data driven architecture). You see that .Net developers are struggling with the same architectural design decission: to use (typed) datasets or to use simple objects in the internal object model. For user interface frameworks and databinding its often easier to work with generic containers that have a known interface to reduce dynamic inspection of objects.

    There are different aspects for each physical tier:

    - usage of database data in the server

    - transformation of deserialized client data on the server

    - usage of deserialized server data on the client

    In the server tier I don't think the OOABL is suited for wrapping each customer row instance by a customer entity thereby creating lots of OOABL class instances. Wrapping a resultset (temp-table) might be a more pheasable approach in this environment, since it will reduce the number of ))ABL class instances compared to the entity approach. But what did you achieve with this approach? A temp-table is already a typed definition. And putting behavior in a resultset wrapper might not be that meaningfull. Sure, you don't have to distribute the temp-table definition in an include file, but you still have to distribute the class declaration in an include file. The class declares a property for most of the temp-table fields, so what's the gain here?

    Statement: "OOABL works best (read: most efficient) in a data driven architecture, where data is decoupled from behavior and data is passed through the tiers in temp-table format."

    Before we can continue with OO...OERA we should have a consensus on this statement.

  • What is the functional difference between a non-persistent .p and a facade class that does its work in the constructor?

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • Whether the search code is in the base component class or in the facade, the same work is being done. The only "extra" overhead in my approach ... overhead which only exists until we are provided with true singletons ... is the extremely small class instance for the facade, but note that the search code in it then no longer has to be in the base component and so that code is removed from every component. Sure seems pretty close to a wash to me, unless there is some huge overhead for having a class instance that doesn't apply to a .p. Given that we don't have multi-threaded sessions, just how many components do you expect to have instantiated in any case?

    Also note, with the pseudo-singleton approach, the first component instantiated in the session will automatically create the session manager instance. With the base component approach, the session manager has to be created externally before the first component is instantiated.

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • Apparently, we

    don't have a consensus on this principle. In fact, I would say that

    the whole notion of decoupling data and behavior was antithetical

    to the principles of OO. You have every right to advocate some

    hybrid architecture like this if you want, but we really ought to

    invent a new name for it to distinguish it from the principles that

    have long been associated with OO. Maybe Pseudo-OO (POO) or

    Hybrid-OO (HOO)?

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • I know .... Data-Object Hybrid ... DOH!

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • What is the functional difference between a

    non-persistent .p and a facade class that does its

    work in the constructor?

    Two remarks:

    1) even when you put all the logic in the constructor, you still instantiate a class instance. So after initialization, you have loaded a class instance and you need a new server call to delete the instance. A non-persistent procedure doesn't suffer from this issue, since you call the server, let the .p do it's work, the result is serialized and the server is released for new requests.

    2) you should use the constructor to initialize a class instance and leave it in a valid state. Real work should be done in a method called from the outside. When a class is complex to setup, you can refactor that code using an assembler pattern. A constructor with lots of logic is mostly an indication of a badly designed class.

  • One remark ... other OO environments get the job done without having to step outside the OO paradigm. We should be able to do so as well.

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com