there. Please let me preface by saying that I have done quite a bit of research and reading around different design patterns within Java, but it is still unclear to me which is appropriate for what I am trying to achieve.
I am also completely open to learning so if the path I am on is poor engineering practice, please let me know and suggest a different path. I do not have any formal engineering background and am self-taught.
Here is what I am trying to achieve. Let's say we have a simple class that aggregates data throughout a request:
#NoArgsConstructor(access = PRIVATE)
public class MyHeaderDecorator {
private static final MyHeaderDecorator INSTANCE = new MyHeaderDecorator();
public MyHeaderDecorator getInstance() {
return INSTANCE;
}
#Getter
private final Map<String, String> customHeadersMap = new HashMap<>();
public MyHeaderDecorator withHeader(final String headerKey, final String headerValue) {
customHeadersMap.put(headerKey, headerValue);
return this;
}
}
Anywhere in our codebase, one can simply use the above Singleton to add more custom header values:
MyHeaderDecorator.getInstance().withHeader("newHeaderKey", "newHeaderValue");
Then, this gets aggregated in our Play filter as such:
public class MyCustomHeaderFilter extends Filter {
#Inject
public MyCustomHeaderFilter(Materializer mat) {
super(mat);
}
#Override
public CompletionStage<Result> apply(
Function<RequestHeader, CompletionStage<Result>> nextFilter, RequestHeader requestHeader) {
return nextFilter.apply(requestHeader).thenApply(result -> {
val customHeaders = MyHeaderDecorator.getInstance().getCustomHeadersMap();
// business logic to transform and insert custom headers into result
return result;
});
}
}
While the above achieves mostly what I am looking to do, these are the reasons why I think I am on the wrong path with the Singleton approach.
Since Singleton aggregates all of the calls ever made on the specific JVM, there are eventually unwanted headers being sent down.
I need the lifecycle of the Singleton to be more request-based and not an actual Singleton. I don't think Singleton fits this pattern.
Researching into different patterns says the pattern I am looking to use is basically a Builder pattern since the information needed to create a full MyHeaderDecorator is in different places. But I don't see a way that I can specify that this is supposed to be PER REQUEST.
I looked into Dependency Injection, but I am quite confused over this topic because I feel, many times, it is interweaved with having a Factory, as well. I'm having a hard time finding learning materials that are simple enough to understand what, exactly, Dependency Injection is doing. I know that it's a mechanism to pass objects and their dependencies without the receiving class having to construct something on their own. But I'm still having a hard time really understanding it. (Which is terrible because I have worked on code bases for 5+ years with the #Inject annotation and just use it because it "works".)
My end goal is to achieve something similar to what I have prototyped above, but have MyHeaderDecorator be scoped to each specific request. Is this even possible? Is it poor practice?
Any help would be much appreciated. Thank you in advance.
Related
How would you suggest to "fix" this class for better testing?
public class Config {
private final ComplexA complexA;
private final ComplexB complexB;
(...)
Config(String[] args) {
complexA = privateMethodCalculatesA(args);
complexB = privateMethodCalculatesB(args);
(...)
}
}
Now, all methods that calculate complexA/B/... are intended to fail-fast if user inserts non-existing or wrong parameters with a System.exit. The issue here is that Config becomes mangled with methods that should be tested in isolation.
Nonetheless same methods should not be publicly exposed and result should be cached as calculation may be expensive.
Just hit the bullet and declare said methods static protected and test them in isolation?
What would be the proper way to do this?
Consider separating ComplexA, ComplexB, etc. into their own classes. That solves the independent testing problem. Then you are faced with the problem of collecting the pieces into a whole. Likely you would favor composition over inheritance for that problem; but either approach might work.
Studying about dependency injection I found some approaches that suggests to inject everything and other saying that it's not necessary to do so.
In my current project, my rule of thumb regarding Dependency Injection is "if the class was created by me, I make it injectable". In other words only classes like SimpleDateFormat, ArrayList, HashMap are newables in my project. My intent doing this approach is that I can #Inject any class anywhere once calling Injector.getApplicationComponent().inject(this) in the Activity. Basically all my classes have a non-args constructor with #Inject.
I was primary using DI because I thought it will improve the performance and memory usage once the new operator is used exclusively by the Dagger generated classes. But I read a post from Dagger 1 developer saying that DI does not have impact on performance and the usage is basically to reduce boilerplate.
The first question is:
Dagger 2 does not any performance advantage in Android application?
My project is running without problems and I think the approach of "inject everything" helps organizing better, despite some drawbacks.
An example of usage of this approach is the following class:
public class TimelineEntryAdapter {
#Inject
Provider<TwitterEntry> mTwitterProvider;
#Inject
Provider<InstagramEntry> mInstagramProvider;
#Inject
Provider<FacebookEntry> mFacebookProvider;
#Inject
TimelineEntryComparator mComparator;
#Inject
public TimelineEntryAdapter() {
}
The second question is:
Is it a bad practice to inject everything in Android?
If the answer for the second question is "No", there is a better way to handle the non-args constructor to create classes? Because when I create an non-args constructor with #Inject annotation and a class need some parameters to work with, I must use setters:
public class SavelArtist {
private MusicBrainzArtist mMusicBrainzArtist;
private DiscogsArtist mDiscogsArtist;
private List<SavelTweet> mTweetList;
private SpotifyArtist mSpotifyArtist;
private List<SavelInstagram> mInstaTimeline;
private List<SavelFacebook> mFacebookTimeline;
private List<SavelRelease> mReleases;
#Inject
Provider<SavelRelease> mReleaseProvider;
#Inject
public SavelArtist() {
}
public void setMusicBrainzArtist(MusicBrainzArtist mbArtist) {
mMusicBrainzArtist = mbArtist;
}
public void setDiscogsArtist(DiscogsArtist discogsArtist) {
mDiscogsArtist = discogsArtist;
}
public void setTweetList(List<SavelTweet> tweetList) {
mTweetList = tweetList;
}
public void setSpotifyArtist(SpotifyArtist spotifyArtist) {
mSpotifyArtist = spotifyArtist;
}
public void setInstaTimeline(List<SavelInstagram> instaTimeline) {
mInstaTimeline = instaTimeline;
}
public void setFacebookTimeline(List<SavelFacebook> fbTimeline) {
mFacebookTimeline = fbTimeline;
}
All the parameters could be set on the constructor, once all are get at the same time in the flow.
Studying about dependency injection I found some approaches that suggests to inject everything and other saying that it's not necessary to do so.
The froger_mcs blog entry you quote doesn't advocate injecting everything. It quite clearly states:
The purpose of this post is to show what we can do, not what we should do.
And it goes on to state a disadvantage of injecting everything:
If you want to use Dagger 2 for almost everything in your project you will quickly see that big piece of 64k methods count limit is used by generated code for injections.
Now, on to your questions:
Dagger 2 does not any performance advantage in Android application?
While Dagger 2 offers a performance advantage over other reflection-based DI frameworks (such as Guice) it doesn't claim to offer any performance advantage over manually constructing your object graphs by calling constructors. You can inspect the generated classes yourself to see that these indeed still eventually call constructors.
Is it a bad practice to inject everything in Android?
Well let's take the following very common Android code:
Intent nextActivity = new Intent(this, NextActivity.class);
startActivity(nextActivity);
Should we extract an IntentFactory and inject this using Dagger 2 merely to avoid the new keyword here? At this point, it is easy to approach pedantry. The advice in the other answer you quoted about the difference between injectables and newables is more flexible and elegant.
Moving on to your next question:
If the answer for the second question is "No", there is a better way to handle the non-args constructor to create classes? Because when I create an non-args constructor with #Inject annotation and a class need some parameters to work with, I must use setters:
Using setters is the wrong approach for parameters. You should distinguish dependencies and parameters. Dependencies normally have the same lifecycle as the object itself. During the lifetime of the object, the methods exposed for that object may be called with different parameters.
I'm not a professional at dependency-management but I use it in my company so here's how I see it.
Inject everything is basically good. I make everything that is used somewhere else ( other modules, classes, packages ) injectable and only static things ( static classes with hidden constructor ), things that get only used internally non injectable.
What's the advantage of it?
Well The dependency system will take care of getting the instance and to discard it. It will clean up automatically. Also using scopes on the classes will enable you to make a class that always has only one instance in the whole application ( multiple threads access it) or make it reusable ( every thread that needs it get's an own instance ).
Also I think you could clean up your classes like this:
#Reusable (Maybe a good Idea?)
public class SavelArtist {
private MusicBrainzArtist mMusicBrainzArtist;
private DiscogsArtist mDiscogsArtist;
private List<SavelTweet> mTweetList;
private SpotifyArtist mSpotifyArtist;
private List<SavelInstagram> mInstaTimeline;
private List<SavelFacebook> mFacebookTimeline;
private List<SavelRelease> mReleases;
private Provider<SavelRelease> mReleaseProvider;
public SavelArtist() {
}
#Inject
public void init(Provider<SavelRelease> mReleaseProvider) {
this.mReleaseProvider = mReleaseProvider;
}
Think about always declaring the scope of the class. Is it a Singleton? Will it be reusable? This little detail can save you, once the application get's complex and big.
The advantage of using the method init to declare all injected variables is to have a clean looking code which is easy maintainable since everything injected is at this one location. But that's actually preference :)
My program gets information from an external source (can be a file, a database, or anything else I might decide upon in the future).
I want to define an interface with all my data needs, and classes that implement it (e.g. a class to get the data from a file, another for DB, etc...).
I want the rest of my project to not care where the data comes from, and not need to create any object to get the data, for example to call "DataSource.getSomething();"
For that I need DataSource to contain a variable of the type of the interface and initialize it with one of the concrete implementations, and expose all of its methods (that come from the interface) as static methods.
So, lets say the interface name is K, and the concrete implementations are A,B,C.
The way I do it today is:
public class DataSource {
private static K myVar = new B();
// For **every** method in K I do something like this:
public static String getSomething() {
return myVar.doSomething();
}
...
}
This is very bad since I need to copy all the methods of the interface and make them static just so I can delegate it to myVar, and many other obvious reasons.
What is the correct way to do it? (maybe there is a design pattern for it?)
**Note - since this will be the backbone of many many other projects and I will use these calls from thousands (if not tens of thousands) code lines, I insist on keeping it simple like "DataSource.getSomething();", I do not want anything like "DataSource.getInstance().getSomething();" **
Edit :
I was offered here to use DI framework like Guice, does this mean I will need to add the DI code in every entry point (i.e. "main" method) in all my projects, or there is a way to do it once for all projects?
The classes using your data source should access it via an interface, and the correct instance provided to the class at construction time.
So first of all make DataSource an interface:
public interface DataSource {
String getSomething();
}
Now a concrete implementation:
public class B implements DataSource {
public String getSomething() {
//read a file, call a database whatever..
}
}
And then your calling class looks like this:
public class MyThingThatNeedsData {
private DataSource ds;
public MyThingThatNeedsData(DataSource ds) {
this.ds = ds;
}
public doSomethingRequiringData() {
String something = ds.getSomething();
//do whatever with the data
}
}
Somewhere else in your code you can instantiate this class:
public class Program {
public static void main(String[] args) {
DataSource ds = new B(); //Here we've picked the concrete implementation
MyThingThatNeedsData thing = new MyThingThatNeedsData(ds); //And we pass it in
String result = thing.doSomethingThatRequiresData();
}
}
You can do the last step using a Dependency Injection framework like Spring or Guice if you want to get fancy.
Bonus points: In your unit tests you can provide a mock/stub implementation of DataSource instead and your client class will be none the wiser!
I want to focus in my answer one important aspect in your question; you wrote:
Note - I insist on keeping it simple like "DataSource.getSomething();", I do not want anything like "DataSource.getInstance().getSomething();"
Thing is: simplicity is not measured on number of characters. Simplicity comes out of good design; and good design comes out of following best practices.
In other words: if you think that DataSource.getSomething() is "easier" than something that uses (for example) dependency injection to "magically" provide you with an object that implements a certain interfaces; then: you are mistaken!
It is the other way round: those are separated concerns: one the one hand; you should declare such an interface that describes the functionality that need. On the other hand, you have client code that needs an object of that interface. That is all you should be focusing on. The step of "creating" that object; and making it available to your code might look more complicated than just calling a static method; but I guarantee you: following the answer from Paolo will make your product better.
It is sometimes easy to do the wrong thing!
EDIT: one pattern that I am using:
interface SomeFunc {
void foo();
}
class SomeFuncImpl implements SomeFunc {
...
}
enum SomeFuncProvider implements SomeFunc {
INSTANCE;
private final SomeFunc delegatee = new SomeFuncImpl();
#Override
void foo() { delegatee.foo(); }
This pattern allows you to write client code like
class Client {
private final SomeFunc func;
Client() { this(SomeFuncProvider.INSTANCE); }
Client(SomeFunc func) { this.func = func; }
Meaning:
There is a nice (singleton-correctway) of accessing an object giving you your functionality
The impl class is completely unit-testable
Client code uses dependency injection, and is therefore also fully unit-testable
My program gets information from an external source (can be a file, a database, or anything else I might decide upon in the future).
This is the thought behind patterns such as Data Access Object (short DAO) or the Repository pattern. The difference is blurry. Both are about abstracting away a data source behind a uniform interface. A common approach is having one DAO/Repository class per business- or database entity. It's up to you if you want them all to behave similarly (e.g. CRUD methods) or be specific with special queries and stuff. In Java EE the patterns are most often implemented using the Java Persistence API (short JPA).
For that I need DataSource to contain a variable of the type of the
interface and initialize it with one of the concrete implementations,
For this initialization you don't want to know or define the type in the using classes. This is where Inversion Of Control (short IOC) comes into play. A simple way to archieve this is putting all dependencies into constructor parameters, but this way you only move the problem one stage up. In Java context you'll often hear the term Context and Dependency Injection (short CDI) which is basically an implementation of the IOC idea. Specifically in Java EE there's the CDI package, which enables you to inject instances of classes based on their implemented interfaces. You basically do not call any constructors anymore when using CDI effectively. You only define your class' dependencies using annotations.
and expose all of its methods (that come from the interface)
This is a misconception. You do want it to expose the interface-defined method ONLY. All other public methods on the class are irrelevant and only meant for testing or in rare cases where you want to use specific behavior.
as static methods.
Having stateful classes with static method only is an antipattern. Since your data source classes must contain a reference to the underlying data source, they have a state. That said, the class needs a private field. This makes usage through static methods impossible. Additionally, static classes are very hard to test and do not behave nicely in multi-threaded environments.
Got design problem, maybe you can help to decide.
My client object can ask for set of objects of class Report. There is defined set of available reports and according to client's permissions different reports can included in returned set. Reports are created per request (every client gets brand new report instances on each request).
Should I use kind of "factory" that will encapsulate reports creation like below:
public class ReportsFactory {
private UserPermissionsChecker permissionsChecker;
public Set<Report> createReports() {
Set<Report> reports = new HashSet<Report>();
if(permissionsChecker.hasAccessTo('report A')) {
reports.add(createReportA());
}
if(permissionsChecker.hasAccessTo('report B')) {
reports.add(createReportB());
}
if(permissionsChecker.hasAccessTo('report C')) {
reports.add(createReportC());
}
return reports;
}
private Report createReportA() {...}
private Report createReportB() {...}
private Report createReportC() {...}
}
Is this right usage of so called simple Factory pattern? Or do you have other suggestions?
** EDIT **
Some comments below say it's not exactly Factory pattern. If not, how could I call that?
I think the design is correct, but this is a wrong usage of the "Factory" word. In the Factory pattern, XxxxFactory creates instances of Xxxx, initializes them if required, but applies no other kind of logic.
This design here seems correct to me, but your class would rather be called ReportsService
And maybe UserPermissionsChecker would be AuthorizationService
Edit: To take into account criticism against the word "Service".
There is currently a quite widespread (I did not say universal) convention in the java world, which consists in having:
A purely descriptive business-model implemented by classes emptied of all logic called (maybe mistakenly) POJOs
All business logic mainly related to an object Xxx implemented in a procedural style in the methods of a class called XxxService.
I personally don't agree with this coding style and I prefer object oriented programming, but whether we like it or not, this convention exists in the Java EE world and has it's coherence.
Judging bye the coding style of the class submitted by the OP, I inferred that he followed this procedural approach. In that situation, it's better to follow the existing convention and call the class that serves as a container for the procedural code which handles Reports a ReportService.
To me this looks a bit of a builder pattern, in a sense you have an object, that you build its data to.
This is in contrast to a factory, where usually returns different concrete types of created objects,
And usually the construction of the data of these objects is done in the CTORs of the concrete classes that objects of them are returned from the factory.
I have a pipeline-based application that analyzes text in different languages (say, English and Chinese). My goal is to have a system that can work in both languages, in a transparent way. NOTE: This question is long because it has many simple code snippets.
The pipeline is composed of three components (let's call them A, B, and C), and I've created them in the following way so that the components are not tightly coupled:
public class Pipeline {
private A componentA;
private B componentB;
private C componentC;
// I really just need the language attribute of Locale,
// but I use it because it's useful to load language specific ResourceBundles.
public Pipeline(Locale locale) {
componentA = new A();
componentB = new B();
componentC = new C();
}
public Output runPipeline(Input) {
Language lang = LanguageIdentifier.identify(Input);
//
ResultOfA resultA = componentA.doSomething(Input);
ResultOfB resultB = componentB.doSomethingElse(resultA); // uses result of A
return componentC.doFinal(resultA, resultB); // uses result of A and B
}
}
Now, every component of the pipeline has something inside which is language specific. For example, in order to analyze Chinese text, I need one lib, and for analyzing English text, I need another different lib.
Moreover, some tasks can be done in one language and cannot be done in the other. One solution to this problem is to make every pipeline component abstract (to implement some common methods), and then have a concrete language-specific implementation. Exemplifying with component A, I'd have the following:
public abstract class A {
private CommonClass x; // common to all languages
private AnotherCommonClass y; // common to all languages
abstract SomeTemporaryResult getTemp(input); // language specific
abstract AnotherTemporaryResult getAnotherTemp(input); // language specific
public ResultOfA doSomething(input) {
// template method
SomeTemporaryResult t = getTemp(input); // language specific
AnotherTemporaryResult tt = getAnotherTemp(input); // language specific
return ResultOfA(t, tt, x.get(), y.get());
}
}
public class EnglishA extends A {
private EnglishSpecificClass something;
// implementation of the abstract methods ...
}
In addition, since each pipeline component is very heavy and I need to reuse them, I thought of creating a factory that caches up the component for further use, using a map that uses the language as the key, like so (the other components would work in the same manner):
public Enum AFactory {
SINGLETON;
private Map<String, A> cache; // this map will only have one or two keys, is there anything more efficient that I can use, instead of HashMap?
public A getA(Locale locale) {
// lookup by locale.language, and insert if it doesn't exist, et cetera
return cache.get(locale.getLanguage());
}
}
So, my question is: What do you think of this design? How can it be improved? I need the "transparency" because the language can be changed dynamically, based on the text that it's being analyzed. As you can see from the runPipeline method, I first identify the language of the Input, and then, based on this, I need to change the pipeline components to the identified language. So, instead of invoking the components directly, maybe I should get them from the factory, like so:
public Output runPipeline(Input) {
Language lang = LanguageIdentifier.identify(Input);
ResultOfA resultA = AFactory.getA(lang).doSomething(Input);
ResultOfB resultB = BFactory.getB(lang).doSomethingElse(resultA);
return CFactory.getC(lang).doFinal(resultA, resultB);
}
Thank you for reading this far. I very much appreciate every suggestion that you can make on this question.
The factory idea is good, as is the idea, if feasible, to encapsulate the A, B, & C components into single classes for each language. One thing that I would urge you to consider is to use Interface inheritance instead of Class inheritance. You could then incorporate an engine that would do the runPipeline process for you. This is similar to the Builder/Director pattern. The steps in this process would be as follows:
get input
use factory method to get correct interface (english/chinese)
pass interface into your engine
runPipeline and get result
On the extends vs implements topic, Allen Holub goes a bit over the top to explain the preference for Interfaces.
Follow up to you comments:
My interpretation of the application of the Builder pattern here would be that you have a Factory that would return a PipelineBuilder. The PipelineBuilder in my design is one that encompases A, B, & C, but you could have separate builders for each if you like. This builder then is given to your PipelineEngine which uses the Builder to generate your results.
As this makes use of a Factory to provide the Builders, your idea above for a Factory remains in tact, replete with its caching mechanism.
With regard to your choice of abstract extension, you do have the choice of giving your PipelineEngine ownership of the heavy objects. However, if you do go the abstract way, note that the shared fields that you have declared are private and therefore would not be available to your subclasses.
I like the basic design. If the classes are simple enough, I might consider consolidating the A/B/C factories into a single class, as it seems there could be some sharing in behavior at that level. I'm assuming that these are really more complex than they appear, though, and that's why that is undesirable.
The basic approach of using Factories to reduce coupling between components is sound, imo.
If I'm not mistaken, What you are calling a factory is actually a very nice form of dependency injection. You are selecting an object instance that is best able to meet the needs of your parameters and return it.
If I'm right about that, you might want to look into DI platforms. They do what you did (which is pretty simple, right?) then they add a few more abilities that you may not need now but you may find would help you later.
I'm just suggesting you look at what problems are solved now. DI is so easy to do yourself that you hardly need any other tools, but they might have found situations you haven't considered yet. Google finds many great looking links right off the bat.
From what I've seen of DI, it's likely that you'll want to move the entire creation of your "Pipe" into the factory, having it do the linking for you and just handing you what you need to solve a specific problem, but now I'm really reaching--my knowledge of DI is just a little better than my knowledge of your code (in other words, I'm pulling most of this out of my butt).