Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I did take too long to decide on using hash maps to cache results.</p> <p>My strategy was not to use a singleton hashmap, but a singleton common objects class storing static instances of cache. I did not see the reason to load a single hashmap with excessive levels of hashtree branching.</p> <p><strong>Reduce the amount of hash resolution</strong></p> <p>If I know that the objects I am dealing with is Employee, Address, Project, I would create three static hashes</p> <pre class="lang-java prettyprint-override"><code>final static private Map&lt;Long, Employee&gt; employeeCache = new HashMap&lt;Long, Employee&gt;(); final static private Map&lt;Long, Address&gt; addressCache = new HashMap&lt;Long, Address&gt;(); final static private Map&lt;String name, Project&gt; projectCache = new HashMap&lt;String name, Project&gt;(); public static void putEmployee(Long id, Employee emp){ employeeCache.put(id, emp); } public static Employee getEmployee(Long id){ return employeeCache.get(id); } public static void putEmployee(Long id, Address addr){ addressCache.put(id, addr); } public static Address getEmployee(Long id){ return addressCache.get(id); } public static void putProject(String name, Address addr){ projectCache.put(name, addr); } public static Address getProject(String name){ return projectCache.get(name); } </code></pre> <p>Putting it all in a single map would be hairy. The principle of efficient access and storage of data is - the more information you have determined about the data, the more you should exploit segregating that data using that information you have. It would reduce the levels of hash resolution required to access the data. Not to mention all the risky and indefinite type casting that would need to be done.</p> <p><strong>Avoid hashing if you can</strong> </p> <p>If you know that you always have a single value of CurrentEmployee and NextEmployee, avoid storing them in the hash of Employee. Just create static instances</p> <pre><code>Employee CurrentEmployee, NextEmployee; </code></pre> <p>That would avoid needing any hash resolution at all.</p> <p><strong>Avoid contaminating the global namespace</strong></p> <p>And if possible, keep them as class instances rather than static instances, to avoid contaminating the global namespace.</p> <p>Why avoid contaminating the global namespace? Because, more than one class would inadvertently use the same name causing untold number of bugs due to global namespace confusion.</p> <p><strong>Keep the cache nearest to where it is expected or used</strong></p> <p>If possible, if the cache is mainly for a certain class, keep the cache as a class instance within that class. And provide an eventbus event for any rare instance that another class would need to get data from that cache.</p> <p>So that you would have an expectable pattern</p> <pre><code>ZZZManager.getZZZ(id); </code></pre> <p><strong>Finalise the cache if possible</strong>,</p> <p>otherwise/and privatise it by providing putters and getters. Do not allow another class to inadvertently re-instantiate the cache, especially if one day your class becomes a general utility library. Also putters and getters have the opportunity to validate the request to avoid a request from wiping out the cache or pushing the app into an Exception by directly presenting the cache with keys or values the cache is unable to handle.</p> <p><strong>Translating these principles into Javascript local storage</strong></p> <p>The GWT page says</p> <blockquote> <p>Judicious use of naming conventions can help with processing storage data. For example, in a web app named MyWebApp, key-value data associated with rows in a UI table named Stock could have key names prefixed with MyWebApp.Stock.</p> </blockquote> <p>Therefore, supplementing the HashMap in your class, with rather crude code,</p> <pre class="lang-java prettyprint-override"><code>public class EmployeePresenter { Storage empStore = Storage.getLocalStorageIfSupported(); HashMap&lt;Long, Employee&gt; employeeCache; public EmployeePresenter(){ if (empStore==null) { employeeCache = new HashMap&lt;Employee&gt;(); } } private String getPrefix(){ return this.getClass()+".Employee"; //return this.getClass().getCanonicalName()+".Employee"; } public Employee putEmployee(Long id, Employee employee) if (empStore==null) { stockStore.setItem(getPrefix()+id, jsonEncode(employee)); return; } employeeCache.put(id, employee); } public Employee getEmployee(Long id) if (empStore==null) { return (Employee) jsonDecode(Employee.class, stockStore.getItem(getPrefix()+id)); } return employeeCache(id); } } </code></pre> <p>Since, the localstore is string based only, I am presuming that you will be writing your own json encoder decoder. On the other hand, why not write the json directly into the store the moment you receive it from the callback?</p> <p><strong>Memory constraints?</strong></p> <p>I cannot profess expertise in this question but I predict the answer for hashmaps to be the maximum memory constrained by the OS on the browser. Minus all the memory that is already consumed by the browser, plugins and javascript, etc, etc overhead.</p> <p>For HTML5 local storage the GWT page says</p> <p>"LocalStorage: 5MB per app per browser. According to the HTML5 spec, this limit can be increased by the user when needed; however, only a few browsers support this."</p> <p>"SessionStorage: Limited only by system memory"</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload