I am looking for a way to log a method call, store it in a database, and then at a later time execute it.
I was thinking to serialize the method call with all its arguments, store it, and then retrieve it back, deserialize it and execute it some how.
So, I am looking for a generic method that will allow me to store the method call with its arguments. Something like
public String myMethod(String arg1, String[] arg2) {
logMethodCall(thisMethodName, allMethodArgumentsSerialized)
}
and the logMethodCall would store the info in a database.
So
a) any code that will allow me to dynamically loop all arguments of a method and serialize them?
b) any code to get the current method name dynamically?
c) any other idea to accomplish something similar
This sounds like the Command pattern, where the actual command object is to be persisted (possibly serialized) before being executed:
command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time. This information includes the method name, the object that owns the method and values for the method parameters
Well, dare I say it, a natural language for handling stuff like this is Lisp. "Code = data", as they say.
If there is a requirement to use Java (for example, if this is to be a small part of a larger system already in Java), consider using ABCL (a Lisp implementation which targets the JVM).
You can spend a lot of time trying to wedge a square peg into a round hole, or just do it the easy way; it's your choice. I really don't mean this in a negative way; it's just an observation.
I haven't seen this pattern before, where you save method calls to the database. I have seen delayed method calls and throttled method calls, but those are always in the running app, they don't survive persistently.
If you want to have persistent actions that can be executed in the future, I think the right way to do this is to create some sort of action or edit object, in the same way that javax.swing.undo.AbstractUndoableEdit works. Then you can log these from anywhere, and execute them from anywhere. The actions can work in a few ways, including:
Store an object type, method name and generic arguments, and execute those later
Provide specific arguments and call a predetermined method name
I would go with the second with a base class, as Swing does, so from your example you would have a myMethodAction class whose objects take the arguments as properties and that knows when told to execute that it should call myMethod.
I would also not have the myMethod implementation do both things. That is going to be a huge headache later. Rather have something like
public void myMethod()
{
if(condition) ... save it ...
else myMethodNow();
}
public void myMethodNow()
{
... do the work now ...
}
Hope that helps.
Related
I am working a small program which can receive several commands. Each of these commands should cause different methods to run. I was thinking that if there were a way to put all the methods into a HashMap and invoke them directly by getting the value paired with the command Key instead of using if statements, it could make things much simpler but as far as I understand this is not possible since methods aren't treated as objects in Java. Still, it will be educative to find out if there is a way to do this.
Methods aren't objects (at least mostly not), but there is a concept that matches what you want: the functional interface, which is defined as an interface that has exactly one abstract method. Two out-of-the-box candidates are Runnable, which takes no parameters, and Consumer, which takes a single parameter and might be the best option if you want to pass in some kind of input (like a Scanner). (If you also want a configurable output, BiConsumer taking a Scanner and a PrintWriter might be suitable.)
Java has a convenience feature called method references that can automatically transform a method into an instance of a functional interface. Put together, it might look like this:
Map<String, Consumer<Scanner>> commands = new HashMap<>();
...
commands.put("foo", someCommand::go); // where someCommand is a variable with a go(Scanner) method
commands.put("bar", new OtherCommand());
commands.put("hello", unused -> { System.out.println("Hello!"); });
...
String commandName = scanner.next();
commands.get(commandName).accept(scanner);
This is not a good idea, make methods as hashmap value don't satisfied shell command complex scene, maybe you can use Runnable Object as value.
Another solution, you can use Spring Shell.
#ShellMethod("commandName")
public String doSomething(String param) {
return String.format("Hi %s", param);
}
I have a method that will process a Collection<Nodes> that is passed in as a parameter. This Collection will be modified, therefore I thought it would be good to first make a copy of it. How do I name the parameter and local variable, e.g. nodes in the example below?
List<Nodes> process(Collection<Nodes> nodes) {
List<Nodes> nodes2 = new ArrayList<>(nodes);
...
}
As another example consider the following where the variable is an int parsed from a String parameter:
public void processUser(final String userId) {
final int userId2 = Integer.parseInt(userId);
...
A good approach to the name variables problem is to use names that suggest the actual meaning of the variable. In your example, you are using names that do not say anything about the method functionality or variables meaning, that's why it is hard to pick a name.
There are many cases like yours in the JDK, e.g. Arrays#copyOf:
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
#SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
In this case they call the parameter original and the local variable copy which perfectly expresses that the returned value is a copy of the parameter. Precisely, copying is what this method does and it is named accordingly.
Using the same reasoning for your case (consider refactoring to give more meaningful names to your method and variables) I would name your local copy of nodes something like processedNodes, to express what that variable is and to be consistent with your method's name.
Edit:
The name of the new method you added in your edit does not provide hints about what it does either. I'll assume that it modifies some properties (maybe in a database) of the user whose id is passed via parameter.
If that is the case (or similar), I think that an appropriate approach you
could apply would be that every method should have a single responsibility. According to your method's name it should process the user, for that you need an int userId. The responsibility of parsing an String userId should be out of the scope of this method.
Using the proposed approach has, among others, the following advantages:
Your class won't change if you have to add additional validation to your input.
Your class won't be responsible for handling NumberFormatException which must be the application responsibility.
Your processUser method won't change if you have to handle different types of inputs (e.g. float userId).
It ultimately comes down to what you want to communicate to future programmers. The computer obviously doesn't care; it's other people you're talking to. So the biggest factor is going to be what those people need to know:
What is the logical (abstract, conceptual) meaning of this variable?
What aspects of how this variable is used could be confusing to programmers?
What are the most important things about this variable?
Looking at your first example, it's kind of hard to understand enough about your program to really choose a good name. The method is called process; but methods generally speaking implement computational processes, so this name really doesn't tell me anything at all. What are you processing? What is the process? Who are you processing it for, and why? Knowing what the method does, and the class it's in, will help to inform your variable name.
Let's add some assumptions. Let's say you're building an application that locates Wi-fi access points in a building. The Node in question is a wireless node, with subclasses Repeater, AccessPoint, and Client. Let's also say it's an online-processed dataset, so the collection of nodes given may change at any time in response to a background thread receiving updates in what nodes are currently visible. Your reason for copying the collection at the head of the method is to isolate yourself from those changes for the duration of local processing. Finally, let's assume that your method is sorting the nodes by ping time (explaining why the method takes a generic Collection but returns the more specific List type).
Now that we better understand your system, let's use that understanding to choose some names that communicate the logical intention of your system to future developers:
class NetworkScanner {
List<Node> sortByPingTime(Collection<Node> networkNodes) {
final ArrayList<Node> unsortedSnapshot;
synchronized(networkNodes) {
unsortedSnapshot = new ArrayList<>(networkNodes);
}
return Utils.sort(unsortedSnapshot, (x,y) -> x.ping < y.ping);
}
}
So the method is sortByPingTime to define what it does; the argument is networkNodes to describe what kind of node we're looking at. And the variable is called unsortedSnapshot to express two things about it that aren't visible just by reading the code:
It's a snapshot of something (implying that the original is somehow volatile); and
It has no order that matters to us (suggesting that it might have, by the time we're done with it).
We could put nodes in there, but that's immediately visible from the input argument. We could also call this snapshotToSort but that's visible in the fact that we hand it off to a sort routine immediately below.
This example remains kind of contrived. The method is really too short for the variable name to matter much. In real life I'd probably just call it out, because picking a good name would take longer than anyone will ever waste figuring out how this method works.
Other related notes:
Naming is inherently a bit subjective. My name will never work for everyone, especially when multiple human languages are taken into account.
I find that the best name is often no name at all. If I can get away with making something anonymous, I will--this minimizes the risk of the variable being reused, and reduces symbols in IDE 'find' boxes. Generally this also pushes me to write tighter, more functional code, which I view as a good thing.
Some people like to include the variable's type in its name; I've always found that a bit odd because the type is generally immediately obvious, and the compiler will usually catch me if I get it wrong anyway.
"Keep it Simple" is in full force here, as everywhere. Most of the time your variable name will not help someone avoid future work. My rule of thumb is, name it something dumb, and if I ever end up scratching my head about what something means, choose that occasion to name it something good.
I used to give names, which reflect and emphasize the major things. So a potential reader (including myself after a couple of months) can get immediately, what is done inside the method just by its signature.
The API in discussion receives an input , does some processing and returns the output. These are the three main things here.
If it is not important, what processing is done and what is the type of input, the most generic is this form:
List<Nodes> process(Collection<Nodes> input) {
List<Nodes> output = new ArrayList<>(input);
...
}
and
public void process(final String input) {
final int output = Integer.parseInt(input);
...
If it is important to provide more information about processing and type of an input, names like: processCollection, inputCollection and processUser, inputUserId are more appropriate, but the local variable is still the output - it is clear and self-explained name:
List<Nodes> processCollection(Collection<Nodes> inputCollection) {
List<Nodes> output = new ArrayList<>(inputCollection);
...
}
and
public void processUser(final String inputUserId) {
final int output = Integer.parseInt(inputUserId);
...
It depends on the use case and sometimes it is even more appropriate to elaborate the processing, which is done: asArray or asFilteredArray etc instead of processCollection.
Someone may prefer the source-destination terminology to the input-output - I do not see the major difference between them. If this serves telling the method story with its title, it is good enough.
It depends on what you are going to do with the local variable.
For example in the first example it seems that is likely that variable nodes2 will actually be the value returned in the end. My advice is then to simply call it result or output.
In the second example... is less clear what you may want to achieve... I guess that userIdAsInt should be fine for the local. However if an int is always expected here and you still want to keep the parameter as a String (Perhaps you want to push that validation out of the method) I think it is more appropriate to make the local variable userId and the parameter userIdAsString or userIdString which hints that String, although accepted here, is not the canonic representation of an userId which is an int.
For sure it depends on the actual context. I would not use approaches from other programming languages such as _ which is good for instance for naming bash scripts, IMO my is also not a good choice - it looks like a piece of code copied from tutorial (at least in Java).
The most simple solution is to name method parameter nodesParam or nodesBackup and then you can simply go with nodes as a copy or to be more specific you can call it nodesCopy.
Anyway, your method process has some tasks to do and maybe it is not the best place for making copies of the nodes list. You can make a copy in the place where you invoke the method, then you can simply use nodes as a name of your object:
List<Nodes> process(Collection<Nodes> nodes) {
// do amazing things here
// ...
}
// ...
process(new ArrayList<>(nodes))
// ...
Just my guess, you have got a collection and you want to keep the original version and modify the copy, maybe a real solution for you is to use java.util.stream.Stream.
Simply put, when naming the variable, I consider a few things.
How is the copy created? (Is it converted from one type to another?...)
What am I going to do with the variable?
Is the name short, but/and meaningful?
Considering the same examples you have provided in the question, I will name variables like this:
List<Nodes> process(Collection<Nodes> nodes) {
List<Nodes> nodesCopy = new ArrayList<>(nodes);
...
}
This is probably just a copy of the collection, hence the name nodesCopy. Meaningful and short. If you use nodesList, that can mean it is not just a Collection; but also a List (more specific).
public void processUser(final String userId) {
final int userIdInt = Integer.parseInt(userId);
...
The String userId is parsed and the result is an integer (int)! It is not just a copy. To emphasize this, I would name this as userIdInt.
It is better not to use an underscore _, because it often indicates instance variables. And the my prefix: not much of a meaning there, and it is nooby (local will do better).
When it comes to method parameter naming conventions, if the thing a method parameter represents will not be represented by any other variable, use a method parameter name that makes it very clear what that method parameter is in the context of the method body. For example, primaryTelephoneNumber may be an acceptable method parameter name in a JavaBean setter method.
If there are multiple representations of a thing in a method context (including method parameters and local variables), use names that make it clear to humans what that thing is and how it should be used. For example, providedPrimaryTelephoneNumber, requestedPrimaryTelephoneNumber, dirtyPrimaryTelephoneNumber might be used for the method parameter name and parsedPrimaryTelephoneNumber, cleanPrimaryTelephoneNumber, massagedPrimaryTelephoneNumber might be used for the local variable name in a method that persists a user-provided primary telephone number.
The main objective is to use names that make it clear to humans reading the source code today and tomorrow as to what things are. Avoid names like var1, var2, a, b, etc.; these names add extra effort and complexity in reading and understanding the source code.
Don't get too caught up in using long method parameter names or local variable names; the source code is for human readability and when the class is compiled method parameter names and local variable names are irrelevant to the machine.
I m trying to develop a simulation application. I need to monitor all java objects in simulation environment. During the execution of a simulation, user defined objects methods are called periodically in each tick. I want to trace all field values and method return values of all objects. For example,
public class Person{
int energy,x,y;
public Person(){
this.energy = new Random().nextInt(0,10);
}
#ScheduledMethod(start=1, interval=1)
void step(){
energy--;
// move random x,y
move();
}
void move(){
this.x= new Random().nextInt(1,50);
this.y = new Random().nexInt(1,50);
} }
In my simulator each person instance energy value in each tick until person is dead is traced and saved. Simulation developers generally uses randomized functions so calling a method twice may not be return the same value like x,y value of the Person.
By using reflection API i can access field values dynamically (energy value of the person can be accessed.) but i need to access method return values (x,y value of the person is changed in each call of the move). When i call method using reflection execution of the method is twiced. So, i need to handle method calling differently.
I mention that i need a monitoring mechanism like JAVA Debugging API. How i can do that during the execution of simulation.I need to watch all fields and method return values like debugging code in execution.
Any idea.
Thanks for ideas
If I understand what you're asking correctly, you want to capture changes in values of raw fields after a call to a method with your annotation.
There are a lot of possible solutions to this, depending on how simple the client code needs to be, and how complicated a framework you want to write, and what you actually need it to do. Here are some ideas:
Have a common base class for simulation objects, and give subclasses a way to store values in a Map<String,Object> you give them, instead of in a raw field; they you supply a subclass of Map which records changes, and your code can simply ask the object what has changed since the last time it was called
Instrument the bytecode on the fly when you load it, using something like BCEL, and replace local field accesses with calls to dynamically generated getters and setters, and do the above bookkeeping there
Do the above, but at compile time by dynamically generating subclasses which contain the bookkeeping code
The last two options are non-trivial to implement, so I'd strongly suggest considering the first option first.
I would like to save some work on my app, is it possible to get the string, for example "level1" and then use the corresponding function, which would be level1();? my main point is not to make a huge switch-case statement, but only make a few level functions in a storage class, and whenever you level up, the string would change to "level" + number where number is the int, so lets say that right now you are in level 10, the function that would run is level10();
I hope i explained it clearly.. sorry if not.. hope you get the idea!
Thanks!
I believe you want to call a method at runtime using its name as a string.
You can do it via reflection.
Class.getMethod(String methodName, Class... parameterTypes)
Don't think of this in terms of method names, unless you want to muck around with reflection (you don't want to, and it's not necessary).
If you really do need to convert strings to method calls – and that's a big "if" – create a Map<String, Foo> where Foo implements some "callable"-like interface. Then a string-to-method lookup is simply:
Map<String, Foo> commands = /* ... */;
Foo foo = commands.get("level42");
foo.bar();
It really sounds like you should just have a
void setLevel(int level)
call. That can feel free to ignore (say) levels 11-14 or whatever... but it would be very ugly to have separate methods and invoke them by name. You can do so with reflection, but you should think about other options first.
Please see the top answer to this post:
Java dynamic function calling
I would also recommend following their advice regarding structure, to create a more object-oriented solution instead of using reflection.
Lets say there is a method that searches for book authors by book id. What should be passed as a parameter to such method - only book.id (int) or whole book object?
Or another example. In java I need to do some work with current url of the page. What should be passed to such method - only request.getRequestURL() or whole request?
I kind of see benefits from each method but can't come up with good rule when to use what.
Thanks.
I am not sure if there is a "rule" to what is best, but I most often pass just the paramaters I need into the method. So in your first example I would only pass in the book.id and in your second example I would only pass in the request.getRequestURL().
I try to avoid passing in more than I need.
I'm going to be a dissenter and argue for passing the entire Book object.
Reason 1: Type checking. If you just pass an integer ID, there's no way to know, looking at code, if you've got the correct "kind" of integer ID. Maybe you've been passing around an integer variable that you think is the Book ID, but it's actually the Author ID. The compiler is not going to help you catch this mistake, and the results are going to be buggy in unexpected ways.
Reason 2: Future proofing. Some have made the argument that if you just pass the ID, you give yourself the option to change the structure of the Book object later, without breaking the doSomethingWithBook(int ID) method. And that's true. On the other hand, if you pass the entire Book object, you give yourself the option to change the internals of doSomethingWithBook(Book book) (maybe it will want to search based on some other field in the future) without breaking any of the (possibly numerous) places you've called doSomethingWithBook. I'd argue that the latter helps you more.
In the case of the Request, I would give a different answer, since I would consider a Request object to be tightly linked to a certain type of interface (web) and therefore would want to limit the use of that object. One question I like to ask myself: if I wanted to switch this web application to be, say, a command-line application, how many classes would have to change? If I'm passing around the Request, that's going to "infect" more classes with web-specific logic.
Weaker connectivity is preferred unless there are specific reasons. When pass book id only to search method you are free to change Book interface without worrying that it might affect other functions. At some moment in future you may discover that you need to do exactly the same job with some URL outside request handler, so avoiding unneeded dependency on request is good. But note, that if you frequently call do_smth(request.getRequestURL()) it may become quite annoying.
This is related to the Law of Demeter, which basically states that objects and methods should only receive exactly what they need, rather than going through another object to get what they actually need. If you need to use multiple fields from a Book in your method, it might be better to just take a book. But in general, you'll have less coupling in a system if you only depend on exactly what you need.
In both your examples, just using the ID or URL would probably be preferable. Particularly in the case of the URL, where (if you want to test the method) it's easy to create a URL to test with but harder (and completely unnecessary) to create a request to pass to the method which will then only use the URL anyway. The method also becomes more generally applicable to other situations than one in which you have a request object.
I would give each method only as much as necessary (so for the second question: just give it request.getRequestURL()).
For the first one I would think about defining both methods (but prefer the id-one, as you can easily get the ID if you have a Book, but not the other way around).
findAuthorsForBookId(int bookId)
findAuthorsForBook(Book b)
Call book.authors().
(Note: this is a dissenting view regarding the accepted answer.)
Well, there is an implicit rule set in context of domain modeling. If the receiver is performing tasks independent of the domain model then you pass the field. Otherwise, you should pass the object and the model specific action is made explicit by the act of the receiver accessing the id property of the 'Book' object. Most importantly, if accessing the property ever evolves beyond simply returning the reference of a field (e.g. certain actions in the property accessor) then clearly you do NOT want to chase all instances in your code where you dereferenced the property before passing it into various methods.
Further considerations are the consequences (if any) of accessing the field before the call cite, or, inside the receiver.
There's no rule actually, you should be straightforward with the info you need, in that case the book.id. If you consider extending / sharing your search in the future, the you can have an overloaded method to accept a book object so that you can search by other attributes of the book object.
Think about maintaining the code in the long run. Any method you expose is a method you'll have to support for your users going forward. If bookId is all that's needed for the forseeable future, then I'd go with just passing in that: that way, anyone who has a bookId can use your method, and it becomes more powerful.
But if there's a good chance that you may need to refactor the lookup to use some other attributes of Book, then pass in Book.
If you're writing a DAO of sorts, you should consider having a BookSelector which can be built up like: new BookSelector().byId(id).bySomethingElse(somethingElse) and pass this selector instead of having a proliferation of findByXYZ methods.
I agree with the previous posters. I wanted to add that if you find yourself needing multiple properties of the object (id, title, author) then I'd suggest passing the object (or an interface to the object). Short parameter lists are generally preferable.
Lets say there is a method that searches for book authors by book id. What should be passed as a parameter to such method - only book.id (int) or whole book object?
I am making the assumption that "book authors" is an attribute of a book. Therefore, I imagine something like the following class:
class Book {
private int id;
private List<Author> authors;
// ... maybe some other book information
public int getID() {
return this.id
}
public void setID(int value) {
this.id = value
}
public List<Author> getAuthors() {
return this.authors.clone();
}
// ...
}
Given an instantiated Book object (aBook), to determine the list of authors, I would expect that I can call aBook.getAuthors(), which requires no parameters.
I would discourage the creation of partially instantiated domain objects. In other words, given a bookid, and looking for a list of authors, I would want the client code to look more like this:
Book aBook = library.findBook(bookid);
List<Author> authors = aBook.getAuthors();
and less like this:
Book bookQuery = new Book().setID(bookid); // partially instantiated Book
Book aBook = library.findBook(bookQuery);
List<Author> aBook = book.getAuthors();
The first version reduces the number of throwaway objects that are created by the client code. (In this case, bookQuery, which isn't a real book.)
It also makes the code easier to read--and therefore to maintain. This is because bookQuery is not doing what the maintenance programmer would expect. For example, I'd expect two Books with the same ID to have the same tite, authors, ISBN, etc. These assertions would fail for bookQuery and aBook.
Thirdly, it minimizes the chance that you will someday pass an invalid (partially instantiated) Book object to a method that is expecting a real Book. This is a bug where the failure (in the method) may happen far away from the cause (the partial instantiation).