A qu. of style: dynamic map JSTL hack to work around missing parameter function calls
Asked Answered
C

0

0

This is not a problem that needs a solution but a question to the experienced developer (hope such things are allowed here too..) about how they judge this proposal.

In JSP/JSTL you can only "call" pure getters (without parameters), i.e. properties. This probably has good reasons (by the way - what would these be..?)

But in everyday work this can be quite limitating. Often you wish you could give some simple Parameter to some getter, just because you need it. What you have to do then is to pre-calculate the data: pre-run all of the "logic" (with forEach and if) of the page in the Java code, create some new wrapper class (only for some very specific thing) and maybe create data structures of them.

Very much work, very laborious, very annoying. For the lazy of us. Am I lazy? May be. Isnt there that old saying that coders are lazy by nature, and thats their incentive for finding interesting new ideas?

OK, here is my hack. I am very curious what you think of it. My project leader does not like it at all..

I have a Map implementation DynamicMap that does not just supply some previously stored values, but get() runs a function, passing in the key and giving out the result as value. The function must be provided by an object implementing DynamicMapCalculator's call(). (the rest of the map methods return some feasible default values like size 1, empty is false etc - not so important) (*)

public class DynamicMap<K, V> implements Map<K, V>
{
  private final DynamicMapCalculator<K, V> calculator;
  public DynamicMap(final DynamicMapCalculator<K, V> calculator)
  {
    this.calculator = calculator;
  }
  public V get(final Object key)
  {
    return calculator.call(key);
  }
}

public interface DynamicMapCalculator<K, V>
{
  public V call(Object key);
}

Now, in an entity we can give out a map via a getter:

public DynamicMap<Node, String> getPathBelowDynMap()
{
  return new DynamicMap<Node, String>(new DynamicMapCalculator<Node, String>()
  {
    private Node node;

    public DynamicMapCalculator<Node, String> init(final Node node)
    {
      this.node = node;
      return this;
    }

    public String call(final Object key)
    {
      return node.getPathBelow((Node) key); // some parent node we want the relative path of this node below
    }
  }.init(this));
}

So, you create an instance implementing the DynamicMapCalculator interface using an anonymous class, passing in the calculator object (this) to an init method (can be built as needed and must return the instance itself, the "inner this") and implementing call() using some method of that object.

So now for the JSP, the reason we did all of this, where access using [] to a map is possible. It's very simple here:

<c:forEach var="node" items="${myNodeList}">
  <li><c:out value="${node.pathBelowDynMap[someParentNode]}"/></li>
</c:forEach>

Well, I find this sophisticated and elegant. Now, crush me.. but with good reasons and good explanations why this is sooo baaaad, please. Of course, I would prefer if you would give me good reasons why this is perfectly OK to do. And sophisticated. And elegant. :)

Thanks for your attention!

(*) By the way, why does Map implement "V get(Object key)" and not "V get(K key)"??

Castellano answered 6/12, 2013 at 14:14 Comment(12)
Are you using JSP only, or Java Server Faces implementation? In JSF, you can use the f:param tag to pass parameters to a method. In JSF 2, you can use real EL to pass whatever parameters you want to methods you invoke.Mosaic
Pure JSP/JSTL (well, and Struts, but..). No JSF or other "modern" thing. But hey, if JSF2 allows free method calls, this may not be that evil ater all? No one wants to say something to this nice little question of good and bad style?Castellano
In terms of style, it ranks as "hack", in my opinion. Yes, it is workable, and yes, that is the kind of thing that many frameworks do. However, it is both fragile (easily breakable) and hard to understand (meta-programming introduces another level which has to be grokked by subsequent programmers). On a similar note, JSF2 provides a non-hack way to provide the functionality along with a lot of other goodness.Mosaic
OK, thanks. But.. why exactly is it "easily breakable"? What could happen? (after all the function call is in the call hierarchy). In my opinion it is not harder to understand (once you got to know the concept of such a dynamic map, of course) than checking what data is pre-calculated in what way. It seems more clear to me, if you can just use the "getter" at the place where you need it.Castellano
And finally, what is the difference (in principle) of using this and JSF2 (which I do not know) allowing free function calls (as I understood it). In terms of "calling functionality from the presentation layer". Sure this may be misused to put too much logic into the page, but as long as it is used to just have "parameterized getters"..? (An no, there is no chance of getting our old and big big project migrated to a modern presentation layer like JSF2)Castellano
Firstly, explain to your supervisor that the framework you are using is old and crusty, and the current requirements of the product go well beyond the framework; hence, you are creating a workaround. As for understanding, the question you have to ask yourself is, "will I be able to understand this in 6 months time?" The breakable part has to do with c:foreach which is elaborated at a different point in the cycle than other parts of JSTL.Mosaic
JSF2 does a LOT of things; it is better to read the documentation. I understand that often you can't upgrade a project, but you have to start now to get across the message to senior management that they are asking for features that are getting more and more expensive to craft by hand, instead of allowing the framework (JSF2) to handle the heavy lifting.Mosaic
Bob, I really appreciate your comments (after all no one else wanted to say anything up to now), but can we please concentrate on the core of the topic? I am not interested in migration strategies to other frameworks (trust me: it is not realistic, and there is no problem with "management"). The question was: given the situation as it is (JSP&JSTL), what are the pros and cons of doing it the way I described it (the DynamicMap idea). Yes, I think I will still understand this in half a year, and I hope any capable colleague will be able too.Castellano
As for the "easily breakable": as stated before, I would like to get detailed explanation that can persuade me, "has to do with ..." does not, Sorry. What could go wrong, concretely? (if you have the time and are willing to spend it, which I have no right to, Thanks again for your time up to here). Feel free to open a real answer with more space than in these comments..Castellano
After studying your code for another 20 minutes, I can say a couple of more things. Your code is very smart; it exudes smartness. While I love writing smart code and appreciate it when I see it, my experience says that if you write code at the limits of your own smartness, you are going to pass the limits of smartness of a lot of other people. Objective test: ask another programmer to implement the [] capability on something other than Node and provide a set of unit tests. Make sure they only get to look at the code for 10 minutes before having to write their own.Mosaic
Wow, how flattering (and only a little bit irony included, right :) Well, dont want to believe it is THAT difficult. Anyhow, got your message. Now lets wait if someone else adds his thoughts on this at some time in the future.Castellano
It's not "ironic" and mildly flattering. Once upon a time, I was very proud of my programming skills and would take all opportunities to write smart code. I had some bad experiences with my own smart code as well as others. At some point, I figured out that if I wanted to take vacations or move on to another project, I had to write really, really good documentation or I had to write more accessible code.Mosaic

© 2022 - 2024 — McMap. All rights reserved.