Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <ol> <li><p>The main question: code reuse</p> <blockquote> <p>If I have some code that has to be reused many times in many classes (rarely with minor parameter changes which is obvious) and concurrent threads, Which approach to go for?</p> </blockquote> <p>Because you're not considering any cut-&amp;-paste, I think you mean:</p> <blockquote> <p>... reused many times by many classes ...</p> </blockquote> <p>What you're asking is nothing special or specific. It's common that code is reused, either within a single app or across multiple apps. The common answer: <strong>use object-oriented design/programming</strong>. Put the code in a class, create an object as an instance, call the object...</p> <p>1a. Reuse via static methods:</p> <blockquote> <p>Make methods static and call (by all classes and concurrent threads) directly as MyMethods.someMethod()</p> </blockquote> <ul> <li>If your class is stateless (no instance variables), this is a great approach. </li> <li>If your class has class-level state (static instance variables only), but the variables are read-only (immutable), this is a good approach. </li> <li>If your class has class-level state (static instance variables only) and the variables change values (mutable), then this can be an appropriate approach. However, if you want your class to be accessible from multiple threads, you <strong>must</strong> make it thread-safe: make your methods synchronized, or have internal code that synchronizes (mutually-exclusive thread access) for all data reads and writes. </li> <li>If your code has object-level state (non-static instance variables), this approach won't work - impossible to access non-static instance variables without instantiating an object.</li> </ul> <p>1b. Reuse via non-static methods, with object instantiation:</p> <blockquote> <p>Make methods non-static and at the time to call them, instantiate the whole class by MyMethods mm = MyMethods(); mm.someMethod();</p> </blockquote> <ul> <li>If your class has static instance variables only, this is a poor approach, because instantiating the object achieves nothing</li> <li>If your class has non-static instance variables - this is the only approach. Mandatory to instantiate an object to access the variables.</li> <li>If the instantiated objects are to be used across multiple threads, they should be (in order of preference): <ul> <li>stateless (no instance variables) - really an option for 1a - no need to instantiate</li> <li>immutable (read-only non-static instance variables)</li> <li>synchronized on all data reads &amp; writes</li> </ul></li> </ul></li> <li><p>Use Strategy pattern</p> <p>Strategy pattern can be good practice. But it has little to do with your overall question. Strategy pattern is used for a specific reason - to swap the implementation of algorithm/processing logic "on-the-fly" without impacting the caller.</p></li> <li><p>Use dependency injection</p> <p>Dependency injection is used for these reasons:</p> <ul> <li>Factory &amp; object cache functionality: removes from your code responsibility for object creation, caching and lookup</li> <li>Intermediation for object sharing: allows various classes to share the same object instance (stored in a given scope/context), without the two classes directly passing the object between themselves</li> <li>"Wiring control" between object instances - setting up object associations, and under CDI, support for interceptor, decorator and observer patterns</li> </ul> <p>This can be very good practice, if used appropriately. In your case, this could only ever apply under option 1b. Dependency injection is all about object instantiation and provision into variables.</p></li> </ol> <p>Problems:</p> <ol> <li><p>Some people would say Unit test wont be possible </p> <ul> <li>Mocking frameworks (and hand-coded unit testing) deal with replacing classes with mock logic, <em>all the time</em>. It's a very normal scenario. You can extend a class to mock it's logic - if it doesn't have final public methods. Also, you can transfer method declarations to an interface, have the class implement the interface, and then mock by implmenting the interface with a different class.</li> <li>In other words, this is not a constraint/force affecting any of your options</li> </ul> <p>1a. See above</p> <p>1b. Memory Load</p> <blockquote> <p>I think it would make too much memory load as a whole class would be instanticated many times just to call one or two methods</p> </blockquote> <p>A small issue. Depending on the data within each object instance (the instance variables), each object instance could be as small as a dozen bytes or as large as megabytes - but usually slanted towards the lower end (often &lt; 1kB). The memory consumption of class <em>code</em> itself is not replicated each time the class is instantiated.</p> <p>Of course, it's good practice to minimise the volume of objects, according to your requirements - don't create a new instance if you already have a useable one. Create fewer object instances and share them across your app - passing them into constructor methods and setter methods. Dependency injection is a good way to share object instances "automatically" without passing them into constructors/setters.</p></li> <li><p>See above</p></li> <li><p>See above</p></li> </ol>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

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