Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #38719 > unrolled thread
| Started by | mike <mikaelpetterson@hotmail.com> |
|---|---|
| First post | 2019-01-29 10:11 -0800 |
| Last post | 2019-02-04 16:33 +0100 |
| Articles | 6 — 4 participants |
Back to article view | Back to comp.lang.java.programmer
How to make my library independent using DI mike <mikaelpetterson@hotmail.com> - 2019-01-29 10:11 -0800
Re: How to make my library independent using DI Martin Gregorie <martin@mydomain.invalid> - 2019-01-29 19:29 +0000
Re: How to make my library independent using DI Andreas Leitgeb <avl@logic.at> - 2019-01-30 10:11 +0000
Re: How to make my library independent using DI mike <mikaelpetterson@hotmail.com> - 2019-01-30 06:13 -0800
Re: How to make my library independent using DI Andreas Leitgeb <avl@logic.at> - 2019-02-01 14:13 +0000
Re: How to make my library independent using DI Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2019-02-04 16:33 +0100
| From | mike <mikaelpetterson@hotmail.com> |
|---|---|
| Date | 2019-01-29 10:11 -0800 |
| Subject | How to make my library independent using DI |
| Message-ID | <c9bc00ee-744c-49e2-b026-08a68841cf48@googlegroups.com> |
Hi,
I am creating a library that can be used with different java applications.
Sometimes I need data from different applications but I want to avoid a direct dependency to these applications.
In my library I have the following classes:
package scrap;
public interface MyDataClass {
String productNumber();
String version();
String time();
}
and
public class MyDataClassImpl implements MyDataClass{
private ExternalDataService externalDataService;
public MyDataClassImpl(ExternalDataService externalDataService){
this.externalDataService = externalDataService;
}
@Override
public String productNumber() {
//Here we have a dependency to an external library call it x
return externalDataService.productNumber();
}
@Override
public String version() {
//Here we have a dependency to an external library call it x
return externalDataService.version();
}
@Override
public String time() {
return calcTime();
}
private String calcTime () {
return "";
}
}
as well as:
package scrap;
public interface ExternalDataService {
public String productNumber();
public String version();
}
Then in the application using this lib I have:
package other;
import scrap.ExternalDataService;
public class AHelper implements ExternalDataService{
@Override
public String productNumber() {
return methodA();
}
@Override
public String version() {
return methodB();
}
public String methodA() {
return "";
}
String methodB() {
return "";
}
}
I have two questions:
1. How can I inject AHelper into MyDataClassImpl without creating a "hard dependency" without using a DI container?
2. If I used a container like Guice how would that look like?
All hints welcome.
br,
Mike
[toc] | [next] | [standalone]
| From | Martin Gregorie <martin@mydomain.invalid> |
|---|---|
| Date | 2019-01-29 19:29 +0000 |
| Message-ID | <q2q9iq$41a$2@news.albasani.net> |
| In reply to | #38719 |
On Tue, 29 Jan 2019 10:11:52 -0800, mike wrote: > Hi, > > I am creating a library that can be used with different java > applications. I've had one for years - just like a similar C library that I started even earlier. I think its best to just let these things grow: - I didn't like the standard C getopt() function, so wrote my own, which can also parse out non-option items on the command line and, knowing I'd use this a lot, it went straight into my support library. Somewhat later it got reimplemented in Java as my ArgParser class: there is no standard equivalent and something like it is essential if you tend to write non- graphical Java programs. - I've done the same for tracing and debugging packages, and added other stuff as and when I needed to write it: circular buffers that hold the last 'n' log messages, a CSV support package, also my own design of regression testing support code .... The trick is simply to recognise that a piece of code may be useful in other places too, write it from the outset to be free from application- specific dependencies, add a regression test harness for it, and lob it into your support package rather than blindly building it into the application you're working on. -- Martin | martin at Gregorie | gregorie dot org
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@logic.at> |
|---|---|
| Date | 2019-01-30 10:11 +0000 |
| Message-ID | <slrnq52u2s.k8o.avl@logic.at> |
| In reply to | #38719 |
mike <mikaelpetterson@hotmail.com> wrote:
> In my library I have the following classes:
> public interface MyDataClass {
> [...]
> }
> public class MyDataClassImpl implements MyDataClass{
> private ExternalDataService externalDataService;
> public MyDataClassImpl(ExternalDataService externalDataService){
> this.externalDataService = externalDataService;
> }
I'd consider this design already fine w.r.t. independence of
lib from app.
> public String productNumber() {
> //Here we have a dependency to an external library call it x
> return externalDataService.productNumber();
> }
You might want to wrap this with a null check for the field, such that
if a user of the lib doesn't provide an implementation (but instead null),
they could still get around.
If the lib doesn't make sense without at least some implementation of
ExternalDataService, then you can leave it as is here, and instead let
the constructor throw some exception for a null argument. There might
even be @NotNull annotations, but I don't know how reliable they are,
or whether they are already available in the versions of Java you use.
> public interface ExternalDataService {
> public String productNumber();
> public String version();
> }
>
> Then in the application using this lib I have:
> public class AHelper implements ExternalDataService{
> [...]
> }
> I have two questions:
>
> 1. How can I inject AHelper into MyDataClassImpl without creating
> a "hard dependency" without using a DI container?
Not sure what you mean by inject, but according to your code snippet,
there is no "hard dependency" to AHelper in your lib.
Unless you strictly disallow "null", there isn't even a necessity
that a user even implements ExternalDataService at all.
> 2. If I used a container like Guice how would that look like?
I don't know Guice, so can't tell.
[toc] | [prev] | [next] | [standalone]
| From | mike <mikaelpetterson@hotmail.com> |
|---|---|
| Date | 2019-01-30 06:13 -0800 |
| Message-ID | <e09b44b3-55fd-4dc9-a16c-156e1bd4fff8@googlegroups.com> |
| In reply to | #38721 |
Hi Andreas, Thanks for your comments. I really appreciate them. > Not sure what you mean by inject, but according to your code snippet, > there is no "hard dependency" to AHelper in your lib. I will definitely check for null. I think I need to do a litte bit more explanation. I need to create an instance of AHelper, in the application using the library,and inject it into my lib. Otherwise I will not be able to access the data from version() and productNumber(). I mean shall I call: MyDataClassImpl( new AHelper()) from the application? And at what point in time should this be done. And if the MyDataClassImpl needs more external data, let's say from BHelper() also, do add the following in my app: MyDataClassImpl(new AHelper(),new BHelper()) ? Thanks for helping out!! //mikael
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@logic.at> |
|---|---|
| Date | 2019-02-01 14:13 +0000 |
| Message-ID | <slrnq58kvi.k8o.avl@logic.at> |
| In reply to | #38722 |
mike <mikaelpetterson@hotmail.com> wrote: > I need to create an instance of AHelper, in the application using the library, > and inject it into my lib. Otherwise I will not be able to access the data from > version() and productNumber(). > I mean shall I call: > MyDataClassImpl( new AHelper()) from the application? That's surely the most straightforward thing to do. There might be other options (even as ugly as involving static fields - don't do that, unless the application really only needs a single instance for the whole VM) > And at what point in time should this be done. Apparently exactly when you need the instance of MyDataClassImpl if more classes of the library need a reference to an > And if the MyDataClassImpl needs more external data, let's say > from BHelper() also, do add the following in my app: > MyDataClassImpl(new AHelper(),new BHelper()) ? If the new data is *necessary* you just add new methods to the interface in the lib, and it will require other applications to upgrade along with the lib (or stick to older versions of the lib) If you're on Java8 or newer, and if it makes sense, you might add default-implementations to the interface for the new methods, so the lib will remain compatible with old apps, (but not with Java7 or older, then) Different helpers (imho) only make sense, if they cover different parts of the library, and aren't always necessary at the same time.
[toc] | [prev] | [next] | [standalone]
| From | Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> |
|---|---|
| Date | 2019-02-04 16:33 +0100 |
| Message-ID | <q39m0g$l2$1@dont-email.me> |
| In reply to | #38719 |
On 2019-01-29 19:11, mike wrote:
> Hi,
>
> I am creating a library that can be used with different java applications.
> Sometimes I need data from different applications but I want to avoid a direct dependency to these applications.
>
> In my library I have the following classes:
>
> package scrap;
>
>
> public interface MyDataClass {
> String productNumber();
> String version();
> String time();
>
>
> }
>
> and
>
> public class MyDataClassImpl implements MyDataClass{
>
> private ExternalDataService externalDataService;
>
> public MyDataClassImpl(ExternalDataService externalDataService){
> this.externalDataService = externalDataService;
> }
>
> @Override
> public String productNumber() {
> //Here we have a dependency to an external library call it x
> return externalDataService.productNumber();
> }
>
> @Override
> public String version() {
> //Here we have a dependency to an external library call it x
> return externalDataService.version();
> }
>
> @Override
> public String time() {
> return calcTime();
> }
>
>
> private String calcTime () {
> return "";
>
> }
> }
>
> as well as:
>
> package scrap;
>
>
> public interface ExternalDataService {
>
> public String productNumber();
>
> public String version();
>
> }
>
>
> Then in the application using this lib I have:
>
> package other;
>
> import scrap.ExternalDataService;
>
> public class AHelper implements ExternalDataService{
>
> @Override
> public String productNumber() {
> return methodA();
> }
>
> @Override
> public String version() {
> return methodB();
> }
>
>
> public String methodA() {
> return "";
> }
>
> String methodB() {
> return "";
> }
> }
>
> I have two questions:
>
> 1. How can I inject AHelper into MyDataClassImpl without creating a "hard dependency" without using a DI container?
> 2. If I used a container like Guice how would that look like?
>
> All hints welcome.
>
> br,
>
> Mike
>
You don't need an "ExternalDataService". It doesn't matter whether the
data is internal or external. You just need a data class and a data
provider class.
public interface Data {
String productNumber();
String version();
String time();
}
public interface DataProvider
extends Supplier<Data>
{}
In order to get hold of DataProvider instances, I would suggest looking
into the java.util.ServiceLoader mechanism (see Javadoc
<https://docs.oracle.com/javase/10/docs/api/java/util/ServiceLoader.html>).
In your own API then, you simply try to load a DataProvider. If you find
one, get your data from there. If not, simply throw up.
--
DF.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web