I'm curious about why the variable var DefaultClient in Go's http package is exported. As the comment of the variable suggests, it is used internally by methods such as Get(). If that is the case, why does it have to be exported?
When I first started coding HTTP related stuff, I always thought I could just use the DefaultClient to send all my requests, until I found out it is not a function that returns a new Client every time, but more like a static pointer variable that always points to the same empty Client instance... so if I decided to modify its properties, all subsequent calls with the DefaultClient will be affected.
Again, what's purpose of exporting this variable?
I can't speak definitively (as I didn't design the package), but if it's exported, it can be modified. This means you can set the timeout etc (which isn't specified by default).
Convenience methods like http.Get are just a wrapper around DefaultClient.Get, it would make sense to be able to modify the timeout of DefaultClient beforehand, but to perhaps use all the other defaults - such as the ability to reuse connections/transports.
Related
Let's say I want to load an FXML document to be used somewhere in my application. As far as I'm aware, there are two ways of doing this:
Call the static FXMLLoader#load(<various resource args>) method.
Initialize an FXMLLoader (with the resource location), and then call load() on that instance.
My question is what exactly "loading" an FXML document does here.
Initially, I assumed the static method would do an entire parse "cycle" on every call, and that creating an instance would allow multiple loads to take advantage of some kind of preprocessed representation, but documentation for the non-static load() method just states;
"Loads an object hierarchy from an FXML document. The location from which the document will be loaded...", which sounds like the document is loaded on every call.
I'm using JavaFX 17.
After spending a fair bit of time with the source, I feel I can give a pretty good overview of how FXML loading functions behind the scenes. That being said, I can't guarantee that there isn't anything I didn't miss. I've thoroughly looked over quite a bit of code I thought to be important, but most isn't all, and I may have simply not noticed something.
This answer should be valid for JavaFX 17.
As a TLDR answering the main concern of my question: As far as I can tell, no information is cached across load() calls, regardless of whether you use the static or non-static versions. That being said, the non-static calls will still give you a slight performance gain, the fastest of which is the load(InputStream inputStream) overload, which (in addition to skipping some argument processing) will prevent the loader from opening a new InputStream on every call.
I've built a call graph (CallGraph Viewer) showing important parts of the FXML loading code in order to make it a bit more digestible.
This is easily the most likely part of my answer to contain inaccuracies. To generate this graph, I simply copied the FXMLLoader code into eclipse and generated connections for parts of the code I deemed important. Unfortunately, the plugin doesn't always correctly parse code containing missing imports, requiring me to write in definitions for a couple of classes, but I left most alone. Additionally, the initial result was incomprehensible and needed a fair bit of manual cleanup, a large portion of which was done simply based on whether I thought something sounded useful or not.
If you are unfamiliar with eclipse's icons, documentation can be found here (make sure to zoom the image, or open it in a new tab, or I doubt you will be able to see much).
Yes, there are three processEndElement() methods with the same signature, they are overridden methods in subclasses of Element.
If you're wondering what I spent all that manual cleanup time on, try not to worry about the individual methods, more the overall structure.
Here's my breakdown of this mess as a step by step recreation of what happens when load() is called:
The application calls one of the public load() methods. This simply calls a matching loadImpl() overload (static if the load() call was static and vice-versa) with the provided arguments. All existing loadImpl() overloads also ask for the class which called them, which the method attempts to provide with a java.lang.StackWalker. No additional processing is done.
After passing the public interface, execution is routed through a hierarchy of loadImpl() calls. Each overload just calls an overload with one more argument than itself, passing on its own arguments and giving null for the missing one (except in the case of a missing charset, which is given a default value).
The more arguments you give to load(), the farther you start in the hierarchy, with non-static versions beginning after the static ones. If you call one of the static overloads, an instance of the FXMLLoader class is created at the final static loadImpl(), which is used to continue onto the non-static calls.
Once reaching the non-static loadImpl() calls, things begin to get interesting. If using the load(void) overload, an InputStream is created based on arguments set when the FXMLLoader instance was initialized, and is given to the next stage in the hierarchy as before. At the final (non-static) loadImpl() (which can be called immediately using the load(InputStream inputStream) overload; this is the fastest method I know of to get from the initial load() call to XML processing), we finally exit the loadImpl() hierarchy, and move to XML processing.
Two things happen here:
a ControllerAccessor instance is given the callingClass argument passed up the loadImpl() hierarchy. I can't exactly explain how this class works, but it contains two Map's; controllerFields and controllerMethods, used in the initialization of controllers.
clearImports() is called, clearing packages (a List) and classes (a Map), both used in further XML processing.
The four variables here (except for maybe the controller ones, I'm a little iffy on them) act as important cache data for the backend XML processing cycle. However, all are cleared between loads (there is no logic controlling their execution, if the load succeeded, the cache data will not have survived), so using an FXMLLoader instance will not improve performance due to data caching (it's still worth using one, however, as the non-static calls skip much of the loadImpl() hierarchy, and you can even reuse the InputStream if using that particular overload).
Next, the XML parser itself is loaded. First, a new instance of a XMLInputFactory is created. This is then used to create a XmlStreamReader from the provided InputStream
Finally, we now begin actually processing the loaded XML.
The main XML processing loop is actually relatively simple to explain;
First, the code enters a while loop, checking the value of xmlStreamReader.hasNext().
During each cycle, a switch statement is entered, routing execution to different process<X>() methods depending on what the XML reader encounters. Those methods process the incoming events, and use an assortment of more "backend" methods to carry out common operations (The 'backend XML processing' section of the call graph is only a small portion of the actual code). These include methods like processImports(), which calls importPackage() or importClass(), in turn populating the packages and classes caches. Those caches are accessed by getType(), a backend method used by many other processing methods.
Additionally, I think that some part of controllers is "assigned" during this stage; processEndElements(), for example, ends up calling getControllerFields() or getControllerMethods(), which access the aforementioned controllerFields and controllerMethods caches, but also sometimes modify them. That being said, the call graph gets a bit too deep for me to easily understand at this point, and those methods are also called later, so I can't be sure.
After XML processing, a controller (controllers? see comment below) is initialized. You can read about controller initialization a bit in James_D's answer here, but I don't have much to say about it, as this is the section I am least confident in understanding.
That being said, it is interesting to note that this code is out of the previous while loop; only one initialization method is called. Either what seems like one call is actually multiple (which is definitely possible; the initialization "method" called is returned by controllerAccessor.getControllerMethods() and "it" is called using the MethodHelper JavaFX class), or only one controller is initialized here (assumedly the controller for the root node) and the others are initialized during parsing. I'd lean towards the first possibility here, but that's based purely on intuition.
Finally (and if you're still reading by now, consider me impressed), we enter cleanup. This stage is super simple;
The ControllerAccessor has its "calling class" variable nulled, and its controllerFields and controllerMethods caches cleared.
The XmlStreamReader instance is nulled.
The root node is returned, and thus the function exits.
Thanks to #jewelsea for links to other answers and for recommending I look at the source.
going on Flutter documentation I found that fetching data was done, sometimes, by using http.Client and sometimes not (just http.get for example). So I was wondering the purpose of using http.Client.
These are the two sites where I found this:
https://flutter.io/cookbook/networking/fetch-data/
https://flutter.io/cookbook/networking/background-parsing/
The http package uses a default IOClient when you use the convenience http.get and http.post methods. However, sometimes you might want to use a specialized Client, for example to change the default HTTPS certificate validation. See this question.
In this circumstance, you can create any Client subclass and use it in the ways shown in your second link. It's rarely necessary, though so the syntax used in your first link is normally sufficient.
I've been using the global module Log.Global and the functions info and debug but my application is growing larger and I need more flexibility. Specifically, I'd like to be able to enable/disable events from different components of the system. I'm wondering what is considering best practice in general (I mention Async since it's the API I'm using but the question is more general).
It seems the API provides at least two ways to do it. There is a ?tags:(string * string) list optional parameters. When used, it appends tags after the log message.
2017-08-23 17:35:38.090225+07:00 Info starting my program -- [foobar: foobar]
I could use that and then filter my log based on the events I want to see. How are tags used in general, are they typically literals or are there other ways of using them?
I could also use more than one logger. For instance, the functor Make_global () : Global_intf creates singleton. I could create one logger for each component. Is there a good reason to choose this approach? besides having different output for each log and setting the log level independently.
I am developing a cleanup/filtering service that has a method that receives a list of objects serialized in xml, and apply some filtering rules to return a subset of those objects.
In a REST-ful service, what verb shall I use for such a method? I thought that GET is a natural choice, but I have to put the serialized XML in the body of the request which works but feels incorrect. The other verbs don't seem to fit semantically.
What is a good way to define that Service interface? Naming the resource /Cleanup or /Filter seems weird mainly because in the examples I see online, it is always a name rather than a verb being used for resource name.
Am I right to feel that REST services are better suited for CRUD operations and you start bending the rules in situations like this service? If yes, am I then making a wrong architectural choice.
I've pushed to develop this service in REST-ful style (as opposed to SOAP) for simplicity, but such awkward cases happen a lot and make me feel like I am missing something. Either choosing REST where it shouldn't be used or may be over-thinking some stuff that doesn't really matter? In that case, what really matters?
REST is about using HTTP the way it was designed. To be RESTful consider (title was REST design :):
URLs should be permalinks to a resource (caching benefits, storing/sharing endpoints etc...)
Because they are permalinks to a resource, having verbs in the URL is a hint that you're on the wrong path (filter is a verb).
A collection of resources can be an endpoint /foos.
If you want to filter the collection of resources, consider querystring params like ?filter= or something like ?ids=1,2,3,4,5.
A GET should not change resources. Note that 'cleanup' implies something getting deleted so be cautious of changes to resources when you do a GET. REST says a GET shouldn't alter resources. Imagine a caching server taking you're cleanup request as a GET and returning OK because t's cached. Caching servers know not to cache a POST, DELETE etc... (that's the way HTTP was designed).
Don't rule out multiple calls - for example, you may do a get to filter and get a set of resources to clean up and then could be followed by many or one DELETE verb calls to do the cleanup.
Sometimes there's a temporal resource like a transaction or a 'job' that could do work like a cleanup. Don't rule out a POST to the resource with the body containing items to cleanup up and it returns a job id. You can then query the jobid for the cleanup progress or status.
It's hard to give exact guidance because the question isn't clear but hopefully the RESTful principlies guidance and thoughts above set you on the right track. If you clarify the exact calls, I'll try and recommend APIs.
So, let's say you wanted to cleanup duplicate foos.
[GET] /foos/duplicates (or /foos?filter=duplicates)
returns a body with identifies to of foos that are duplicates. Let's say that returns 1,2,5 (could be names).
Then you could issue:
[DELETE] /foos with the body being an array containing 1,2,5 (or names if unique). the delete call is passive so even if the GET call is cached according to REST principles it's fine.
It's also possible and valid to not go the REST route such as POX or JOSN RPC over http but just realize at that point that it's not REST. And that's fine but you're not getting the benefits of REST described in fielding's thesis.
http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
Also, read this:
http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http
EDIT:
After reading the comment where you clarified you're sending the server a set of objects (not persisted server side) and it returns the subset with the dupes filtered out (like a server side helper function), some options are:
Do this client/browser side if possible - why take the network roundtrip to filter out dupes out of collection?
If for some reason only the server has specific knowledge/data to determine that two items are functional equivalent (even though data not exactly the same), then consider POSTing the data set to the server with the response body containing the unique/filtered set. Even though the server isn't persisting the set, it would fall into a 'temporal' object or set and the server is modifying it. It's not conceptually a GET of server resources and caching offers no benefits in that scenario.
Last question first: What really matters is getting the job done in a way that is
Correct
As easy to use as practical
Easily maintained by future programmers (likely to include yourself)
REST is a natural fit for operations on resources where each URL matches some object that can be manipulated. It is a less natural fit for other uses, but these are more guidelines than actual rules. Others have pointed out the original dissertation on REST, but it is worth remembering that few implementations are pure.
If you have several URLs that perform these transformative kinds of functions, consider putting them in their own special URL space, like /api/filter and /api/transliterate, etc.. That will help users and maintainers alike know that certain URLs aren't REST, but are more like remote procedure calls. Posting data to these URLs results in you getting some kind of data back.
If you get stuck on specific names you should make a list of candidates, have a few beers, then choose one from the list. That's what I do when I get stuck on minutia.
SOAP is a neat protocol and has its uses, but it tends to be very heavy. Good documentation and consistency are probably more important to your budding API than using any specific technology.
Where do you normally store your PL/SQL constants? On the package-body level? In the specification? I've also seen some people holding constants in a specialized package just for constants. What are best practices in this area?
Thanks.
One downside to having constants in a package body or spec is that when you recompile the package, any user sessions that had the package state in the PGA would get ORA-04068. For this reason, in one large development environment we adopted the convention of having a separate spec-only package to hold the constants (and package globals if any) for each package. We'd then impose a rule saying that these spec-only packages were only allowed to be referenced by their "owning" package - which we enforced at code review. Not a perfect solution, but it worked for us at the time.
For the same reason, I'd never recommend one-constant-package-to-rule-them-all because every time someone needs to introduce a new constant, or modify an existing one, all user sessions get ORA-04068.
In many cases, you want to keep them in the specification so other packages can use them, especially as parameters when calling functions and procedures from your package.
Only when you want to keep them private to the package, you should put them int the body.
Having a package just for constants might be a good idea for those constants that are not related to any piece of code in particular, but relevant for the whole schema.
For our application, all constants are in a table. A simple function is used to extract them. No problem with recompilation, ORA-04068, ...
Best option in my opinion. Store the "constant" in a table and create a generic function to get the values. No 04068 😀
I would prefer the constants to be, by default, in the package body unless you use the constant as a parameter value for one of your public package procedures/functions or as a return value for your functions.
The problem with putting your constants in the package specification is that if you need to change the constant's type, other packages might fail that use the constant because it was just there. If the constant was private in the first place, then you don't need to perform an impact analysis for each change.
If you need to store contants like default language or stuff like that, then I would encapsulate those contants in functions like get_default_language etc. and keep the constants private.
I'd have a concern about having "one package to rule the constants" because package state -- constants, variables, and code -- get cached in the user's PGA at first invocation of any public variable or package. A package constant, if public, should be scoped to the package, and used by only by the methods of the package.
A constant whose scope spans packages should be in a code table with a description, joined in as required. Constant's aren't and variables don't, after all. Having a key-value-pair table of "constants" makes them all public, and makes changing them dynamically possible.
What if we use parameterless function named the same way as constant instead of using constant in the package. In that case we can add new function/constant to the package, change returning value of function or even remove some function from the package freely and we'll not get ORA 04068 after recompile it.
Inside implementation part of the function in the package body we can use constant as a returning value, though it's unnecessarily because we obviously can't change returning value. Also we can use in function signature some special performance technics, such as deterministic or maybe even result cash.
As a positive side effect we get ability to use constant in sql queries.