Currently, we are using JEXL expression evaluator in our microservice. However, we would like to have the flexibility to change this to some other expression evaluator in future. The issue here is that the expression evaluators from different vendors do not inherit methods from a common interface. Thus, different expression evaluators could have different methods as well as different method signatures, although under the hood they do provide similar functionality. How can I approach this problem in a way that avoids changing the entire code base in case we do decide to change the expression evaluator in future ? It would be helpful if the answer includes a sample code implementing this scenario.
Well, #Admx mentions the adapter pattern in comments, and normally in situations like this that would be a good idea. It boils down to three steps:
Write an interface that defined what you need an expression evaluator to do;
Implement that interface using JEXL
Encapsulate creation of evaluators in a factory so that you can swap implementations whenever you want.
In this case, there is a problem with that idea: The expression language is part of the interface.
It's quite unlikely that any other 3rd party expression evaluator is going to implement the same expression language. That means that if you swap out JEXL for something else, then you'll have to edit all the expressions you need it to evaluate.
Is that really a direction you expect you project to evolve in? Probably not.
Since you can't really use JEXL without tying your product to JEXL, you might just want to incorporate JEXL source into your own code base, and maintain it from there as if it was your own. It's Apache-licensed and not too big, so that is certainly doable. You don't need to do this now, but it's an option you can turn to if JEXL ends up causing you trouble.
Related
I have got a problem where I calculate a number and according to this number I have to call a specific method. I ended up with the idea of creating an enum in which each element calls another method. Just as described in this post https://stackoverflow.com/a/4280838/2426316
However, the poster of that answer also mentioned that it would not be considered a very good design, so that I am wondering what I should do. Is it safe to implement an algorithm that uses this design? If not, what else can I do?
The Java Enum type is a language level support (syntactic sugar) for the type-safe enum pattern.
One of the advantages of the type-safe enum pattern and the Java Enum type (compared to other solutions such as C# enums) is that it's designed to support methods, even abstract ones.
Possible usage:
places where you would use the Strategy pattern, but have a fixed set of strategies
replace switch statements with polymorphism (prefered)
...
For more information:
Effective Java, by Joshua Bloch.
First edition includes the type-safe enum pattern
Second edition includes the Java Enum type
Refactoring, by Martin Fowler (e.g. Replace conditional with polymorphism)
Well, safety probably isn't the issue here. It is uncommon an can be difficult to follow though.
My recommendation would be to build around this in one of two ways:
Use ENUMS but don't include the function calls in the ENUM code itself. Rather have a function explore(Level1 level){...} that has a switch statement which differentiates by the level passed.
Use Lambda expressions. This is the cleaner solution as it allows you to pass functions as arguments; sadly Java won't support this method natively until Java 8 is released. There are however implementations to simulate Lambda expressions, the best known probably being lambdaj.
I'm studying the visitor pattern and I wonder how this pattern is related to the open/closed principle. I read on several websites that "It is one way to follow the open/closed principle." (citated from wikipedia).
On another website I learned that is follows the open/closed principle in such a way that it is easy to add new visitors to your program in order to "extend existing funcionality without changing existing code". That same website mentions that this visitor pattern has a major drawback: "If a new visitable object is added to the framework structure all the implemented visitors need to be modified." A solution for this problem is provided by using Java's Reflection framework.
Now, isn't this solution a bit of a hack solution? I mean, I found this solution on some other blogs as well, but the code looks more like a workaround!
Is there another solution to this problem of adding new visitables to an existing implementation of the visitor pattern?
Visitor is one of the most boilerplate-ridden patterns of all and has the drawbacks regarding non-extensibility that you mention. It is itself a sloppy workaround to introduce double dispatch into a single-dispatch language. When you consider all its drawbacks, resorting to reflection is not such a terrible choice.
In fact, reflection is not a very bad choice in any case: consider how much today's code is written in dynamic languages, in other words using nothing but reflection, and the applications don't fall apart because of it.
Type safety has its merits, certainly, but when you find yourself hitting the wall of static typing and single dispatch, embrace reflection without remorse. Note also that, with proper caching of Method objects, reflective method invocation is almost as fast as static invocation.
It depends on precisely what job the Visitor is supposed to accomplish, but in most cases, this is what interfaces are for. Consider a SortedSet; the implementation needs to be able to compare the different objects in the set to know their ordering, but it doesn't need to understand anything else about the objects. The solution (for sorting by natural order) is to use the Comparable interface.
This is a terminological question, which makes it hard to ask!
Let me give an example. Suppose I am writing a symbolic-differentiation algorithm. I have an abstract class Exp that is a superclass of a bunch of expression types (sums, integrals, whatever). There is an abstract method derivative such that e.derivative() is supposed to be the derivative of the expression e. All the concrete subclasses of Exp (imagine a whole hierarchy here) implement a derivative method that captures knowledge of how to differentiate expressions of that type. A given method will typically compute the derivative of an expression by combining derivatives of subexpressions.
The details of the example are not important. The important thing is that all of these scattered methods can be considered pieces of one (recursive) algorithm. This is not true of all methods, but it's true of many of them (and the use of overloading to reuse the same method name for fundamentally different operations is considered a Bad Idea). The question is, what is the term for 'derivative,' considered as a single function? It's not a method; in another language it would be a function, and the various clauses (what to do with sums, what to do with integrals) would be in the same place. I don't care which approach or languaage is better, or whether that style can be used in Java. I just want to know what term to use for 'derivative' considered as a single function or procedure (the idea is not limited to functional programming, nor is recursion a key feature). When I tell someone what I did today, I'd like to say "I tried to implement a symbolic-differentation __, but every algorithm I thought of didn't work." What goes in the blank?
I assume the same issue comes up for other OO languages, but Java is the one I'm most familiar with. I'm so familiar with it that I'm pretty sure there is no standard term, but I thought I would ask our fine battery of experts here before jumping to that conclusion.
That sounds like "normal" subtype polymorphism. The subclasses/implementations do the work but the interface is defined in a base-type. This "scatter" method is in contrast to say, the Visitor Pattern ("as good as Java gets") or Pattern Matching (not in Java) or a big manky switch/if-else controller. I'm not sure I really would call it anything else as an aggregate.
Addendum: you may find Are Scala case-classes a failed experiment? a nice read. In particular, the comments which talk about "column" vs. "row" organization and the "difference of locality" each approach has:
...in OO, you divide by rows. Each row is a module, called a class. All the functions pertaining to that data variant are grouped together. This is a reasonable way of organizing things, and it's very common. The advantage is that's easy to add a data variant ... However the disadvantage is that it's hard to add new functions that vary by data type. You have to go through every class to add a new method.
I'm not sure if this is what you're looking for but I think I can answer this in terms of design pattern terminology. Your example sounds vaguely like the GoF Strategy Pattern. Here is an example of the Strategy Pattern implemented in Java.
On the contrary, I think that "method" is the standard term for this in the Java context.
A polymorphic function can be applied to values of different types. The function may be implemented by more than one Java method.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Much of my programming background is in Java, and I'm still doing most of my programming in Java. However, I'm starting to learn Python for some side projects at work, and I'd like to learn it as independent of my Java background as possible - i.e. I don't want to just program Java in Python. What are some things I should look out for?
A quick example - when looking through the Python tutorial, I came across the fact that defaulted mutable parameters of a function (such as a list) are persisted (remembered from call to call). This was counter-intuitive to me as a Java programmer and hard to get my head around. (See here and here if you don't understand the example.)
Someone also provided me with this list, which I found helpful, but short. Anyone have any other examples of how a Java programmer might tend to misuse Python...? Or things a Java programmer would falsely assume or have trouble understanding?
Edit: Ok, a brief overview of the reasons addressed by the article I linked to to prevent duplicates in the answers (as suggested by Bill the Lizard). (Please let me know if I make a mistake in phrasing, I've only just started with Python so I may not understand all the concepts fully. And a disclaimer - these are going to be very brief, so if you don't understand what it's getting at check out the link.)
A static method in Java does not translate to a Python classmethod
A switch statement in Java translates to a hash table in Python
Don't use XML
Getters and setters are evil (hey, I'm just quoting :) )
Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python
(And if you find this question at all interesting, check out the link anyway. :) It's quite good.)
Don't put everything into classes. Python's built-in list and dictionaries will take you far.
Don't worry about keeping one class per module. Divide modules by purpose, not by class.
Use inheritance for behavior, not interfaces. Don't create an "Animal" class for "Dog" and "Cat" to inherit from, just so you can have a generic "make_sound" method.
Just do this:
class Dog(object):
def make_sound(self):
return "woof!"
class Cat(object):
def make_sound(self):
return "meow!"
class LolCat(object):
def make_sound(self):
return "i can has cheezburger?"
The referenced article has some good advice that can easily be misquoted and misunderstood. And some bad advice.
Leave Java behind. Start fresh. "do not trust your [Java-based] instincts". Saying things are "counter-intuitive" is a bad habit in any programming discipline. When learning a new language, start fresh, and drop your habits. Your intuition must be wrong.
Languages are different. Otherwise, they'd be the same language with different syntax, and there'd be simple translators. Because there are not simple translators, there's no simple mapping. That means that intuition is unhelpful and dangerous.
"A static method in Java does not translate to a Python classmethod." This kind of thing is really limited and unhelpful. Python has a staticmethod decorator. It also has a classmethod decorator, for which Java has no equivalent.
This point, BTW, also included the much more helpful advice on not needlessly wrapping everything in a class. "The idiomatic translation of a Java static method is usually a module-level function".
The Java switch statement in Java can be implemented several ways. First, and foremost, it's usually an if elif elif elif construct. The article is unhelpful in this respect. If you're absolutely sure this is too slow (and can prove it) you can use a Python dictionary as a slightly faster mapping from value to block of code. Blindly translating switch to dictionary (without thinking) is really bad advice.
Don't use XML. Doesn't make sense when taken out of context. In context it means don't rely on XML to add flexibility. Java relies on describing stuff in XML; WSDL files, for example, repeat information that's obvious from inspecting the code. Python relies on introspection instead of restating everything in XML.
But Python has excellent XML processing libraries. Several.
Getters and setters are not required in Python they way they're required in Java. First, you have better introspection in Python, so you don't need getters and setters to help make dynamic bean objects. (For that, you use collections.namedtuple).
However, you have the property decorator which will bundle getters (and setters) into an attribute-like construct. The point is that Python prefers naked attributes; when necessary, we can bundle getters and setters to appear as if there's a simple attribute.
Also, Python has descriptor classes if properties aren't sophisticated enough.
Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python. Correct. Python uses optional arguments instead of method overloading.
The bullet point went on to talk about closure; that isn't as helpful as the simple advice to use default argument values wisely.
One thing you might be used to in Java that you won't find in Python is strict privacy. This is not so much something to look out for as it is something not to look for (I am embarrassed by how long I searched for a Python equivalent to 'private' when I started out!). Instead, Python has much more transparency and easier introspection than Java. This falls under what is sometimes described as the "we're all consenting adults here" philosophy. There are a few conventions and language mechanisms to help prevent accidental use of "unpublic" methods and so forth, but the whole mindset of information hiding is virtually absent in Python.
The biggest one I can think of is not understanding or not fully utilizing duck typing. In Java you're required to specify very explicit and detailed type information upfront. In Python typing is both dynamic and largely implicit. The philosophy is that you should be thinking about your program at a higher level than nominal types. For example, in Python, you don't use inheritance to model substitutability. Substitutability comes by default as a result of duck typing. Inheritance is only a programmer convenience for reusing implementation.
Similarly, the Pythonic idiom is "beg forgiveness, don't ask permission". Explicit typing is considered evil. Don't check whether a parameter is a certain type upfront. Just try to do whatever you need to do with the parameter. If it doesn't conform to the proper interface, it will throw a very clear exception and you will be able to find the problem very quickly. If someone passes a parameter of a type that was nominally unexpected but has the same interface as what you expected, then you've gained flexibility for free.
The most important thing, from a Java POV, is that it's perfectly ok to not make classes for everything. There are many situations where a procedural approach is simpler and shorter.
The next most important thing is that you will have to get over the notion that the type of an object controls what it may do; rather, the code controls what objects must be able to support at runtime (this is by virtue of duck-typing).
Oh, and use native lists and dicts (not customized descendants) as far as possible.
The way exceptions are treated in Python is different from
how they are treated in Java. While in Java the advice
is to use exceptions only for exceptional conditions this is not
so with Python.
In Python things like Iterator makes use of exception mechanism to signal that there are no more items.But such a design is not considered as good practice in Java.
As Alex Martelli puts in his book Python in a Nutshell
the exception mechanism with other languages (and applicable to Java)
is LBYL (Look Before You Leap) :
is to check in advance, before attempting an operation, for all circumstances that might make the operation invalid.
Where as with Python the approach is EAFP (it's easier to Ask for forgiveness than permission)
A corrollary to "Don't use classes for everything": callbacks.
The Java way for doing callbacks relies on passing objects that implement the callback interface (for example ActionListener with its actionPerformed() method). Nothing of this sort is necessary in Python, you can directly pass methods or even locally defined functions:
def handler():
print("click!")
button.onclick(handler)
Or even lambdas:
button.onclick(lambda: print("click!\n"))
In the system which I'm currently developing I often have to navigate an object tree and based on its state and values take actions. In normal Java this results in tedious for loops, if statements etc... Are there alternative ways to achieve tree navigation, similar to XPath for XML? I know there is JXPath and OGNL, but do you know any other libraries for such purpose? Do you know any libraries which generate bytecodes for specific tree navigation expressions to make the processing as fast as Java native fors and ifs?
You may want to consider Jakarta Bean Utils
String street = (String) PropertyUtils.getProperty(user, "address.street");
You can navigate through the object graph using a dot notation. You can access also indexed properties. More details on the docs.
One drawback is that Bean Utils expects that the graph you are navigating does not contain null references.
The code snippet below would throw a NPE
Person person = new Person();
person.setAddress(null);
String street = (String) PropertyUtils.getProperty(person, "address.street");
To overcome this limitation my team implemented a class that creates instances of all null references of a graph on demand. This code is based on reflection and dynamic proxies (CGLIB).
Can I ask you why you would not like OGNL/JXPath ? Obviously you may have done your research to say no but I would like to know why OGNL is not solving a purpose that it was designed to solve.
Also google-collections has some functors (in addition to commons collections mentioned above) which may be worth looking at.
Jakarta collections ( http://commons.apache.org/collections/apidocs/ ) allow you to apply predicates, functors, etc... on collection members. Is this the direction you are looking for?