Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Best practices for data-binding field name management

    To anyone and everyone on the forum...

    I'm wondering what coding strategies people use with regards to maintaing the String references to field names that are specified in DataSources and are used throughout the databinding process. For example, if there's a field called "customerName" in the DataSource, chances are excellent that the String "customerName" is going to be used in both client-side and server-side code. At the minimim, that String is going to be typed in the .ds.xml file, and some client-side code.

    I have a number of goals in mind:
    1. Minimizing opportunity for runtime and/or development bugs stemming from typos with field name strings. Even case-sensitivity can burn you here: "customername" vs. "customerName" and so on.
    2. Maximizing the ability of an IDE (Eclipse, IDEA, etc.) to "find the usages" of a given field name and associated code. For example, I may want to easily determine where this "customerName" piece of data is being used in the app.
    3. Being able to share this information across projects/applications
    4. Being able to easily specify via an API what field names are going to be required by some server-side call, and being able to know what I'm getting back from such a call.

    That last one is the killer, I think. When some DMI method, for example, is going to look into a very generic map of "parameters" and attempt to pull values out of it via string keys, I need to know as easily as possible what those keys are (and what data types the method is expecting, ideally). Likewise, if it's going to return a collection of Records, I want to know what's in those Records (if they're not specified directly by the .ds.xml file itself). Otherwise, one must rely on having access to the source code (including .ds.xml files) and/or maintaining a potentially large, parallel code base in the form of human-readable (as opposed to IDE-readable) English documentation. Someone changes the Java without changing the English, and bam... potential runtime error or very confused/delayed programmer.

    One nice thing about GWT-RPC is that a given server method-call publishes a specific API that is compile-time checkable, telling you exactly what the method requires as input, and exactly what, if anything, you're going to get back as output. For all of the well-publicized denigrations of GWT-RPC, the loss of that communication to the developer, and its enforcement via the compiler, has non-trivial productivity implications. I'm trying to determine the "best practices" with SmartGWT to recover some of that lost communication and safety.

    It seems like some kind of namespace class has to be created somewhere that contains a bunch of constants, like this:

    Code:
    public class CustomerFields
    {
        public static final String FIELD_CUSTOMER_NAME = "customerName";
        public static final String FIELD_CUSTOMER_ID = "customerID";
       // etc...
    }
    
    // Usage example in DMI call...
    
    Map args = dsRequest.getClientSuppliedValues();
    
    String customerID = (String)args.get(CustomerFields.FIELD_CUSTOMER_ID);
    The question then becomes, where does such a class live? A separate project or module external to a particular app where it's being used, to allow for reuse?

    How have other people wrestled with this issue? I've been trying a variety of things like the namespace class above, and don't love any of them... hence this post.

    Thanks.

    #2
    Big picture: use automated tests to avoid regressions, especially via Selenium.

    Compile-time checking is just another form of automated test. In the case of GWT-RPC, it's an incredibly time-consuming, architecture-hobbling form of test to implement, and it doesn't even test the right thing (ie does the app work).

    Many compile-time tests are like this. We recommend focusing on runtime tests.

    We also recommend focusing on testing the actual functionality of the application rather than intermediate results which could easily be subject to *valid* change after refactoring, causing tests to be thrown away.

    Finally, we can't understand the concern here:

    Code:
    That last one is the killer, I think. When some DMI method, for example, is going to look into a very generic map of "parameters" and attempt to pull values out of it via string keys, I need to know as easily as possible what those keys are (and what data types the method is expecting, ideally). Likewise, if it's going to return a collection of Records, I want to know what's in those Records (if they're not specified directly by the .ds.xml file itself).
    Could you spell out a scenario in which you do not know what you are returning? It seems that the DataSource file already tells you what's in the records.

    Comment


      #3
      It's hard to argue against using automated tests of actual application functionality, but my concerns are closer to the realtime code/run/debug cycle that a developer will go through for so many hours of the day, often involving learning or examining how one is going to interact with someone else's code. Perhaps a developer is considering some refactoring exercise, or the need to a piece of data somewhere: "What part of the app might I break?" becomes a very valid question. Selenium isn't going to help in this continuous workflow process, perhaps during a time when the ultimate application functionality isn't finished yet, or when the system is not even compilable.

      Could you spell out a scenario in which you do not know what you are returning?
      If I'm calling server-side code that I wrote or have access to, then of course I know what I'm returning. I'm sold on not using GWT-RPC , but you're ignoring the very real issue I described with the information conveyance of having a type-checked, non-opaque API in a server call. It's analogous to why one would prefer seeing "Map<String,Date>" over "Map" in one's code. In the first place I know what I'm dealing with. In the second case, who knows? Can I "test" the opaque Map during debugging and inspect it and so on? Of course, but it's a lot slower to code that way.

      More specifically, in certain use cases I've had very good success with using a single DMI call that builds up a complex data structure via multiple threads that get spawned server-side. The data structures don't necessarily directly translate to a single UI component, or aspect thereof. I'm trying not to allow the UI requirements (which are very complex) to overly influence my server-side implementations and/or communications with the server. To some extent that's unavoidable -- we will agree there.

      In other cases, I might want to return a compound status result to some kind of custom server-side operation. I'm using a single Record with multiple attributes for that, ones that don't directly relate to what's described in my data source, but are CONCEPTUALLY related to that data. DMI again works perfectly for this, and I'm specifying a single DMI class in the .ds.xml file via 'serverObject'

      Maybe I need to be creating a lot more DataSources than the bunch I already have -- I'm trying to avoid a sheer explosion in the number of implementation files required here, which seems counterproductive (something that your DTO-avoidance strategy can relate to, I think). That still doesn't address the nitty-gritty issues I laid out in my original post, of how I should most productively interact with the fields of those DataSources.

      Comment


        #4
        Why are you assuming that Selenium tests are not used during the code/run/debug cycle? Selenium need not be limited to testing a final application; at Isomorphic HQ, for example, we run thousands of individual test cases via Selenium.

        As far as the broader issue, what you seem to be describing is that you've written a bunch of server-side code that puts together nested, non-typesafe collections. So far, that has nothing to do with SmartGWT - it's just your own code and your own choices regarding degree of type safety. You could be using beans with formal getters or collections such as Maps, you chose collections. DMI can transmit either one, with no additional code required.

        If you're having actual issues server-side where you're getting the names of Map keys wrong in your code or can't figure out the impact of changes, add type safety or unit tests as you see fit - you can call the DMI logic from a JUnit test if you like. This is just ordinary Java stuff.

        As far as transmission to the client, we again allow you to be as formal or informal as you like; you can describe the entire structure being transmitted with a series of nested DataSources, or you can be less formal - it's up to you. If you introduce DataSources, due to features like dataSourceField.valueXPath, you can keep the data structure delivered to the client the same regardless of changes to server code.

        You can use Selenium-based tests or even JUnit-driven server-side tests that check DSResponses (see Standalone DataSource usage) if this is an area where you're introducing bugs with your changes.

        Overall: type-safety vs verbosity is not a new tradeoff, nor one introduced by SmartGWT.

        If there is anything different about SmartGWT, it's that we *allow* you to be less formal instead of requiring endless DTOs and other artifacts even when they are inappropriate. But it's up to you how formal or informal you want to be.

        Comment

        Working...
        X