New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue #13: First approach #33
Conversation
Thanks, I'll try to take a look this week. For the first question, this test case illustrates why multiple field bindings are required. Basically the same key could have multiple field bindings. |
return injectionMap; | ||
} | ||
|
||
public String getClassPackage() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PackageName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it comes from the variable name in ExtraInjector
. I didn't want to change the existing code.
The biggest issue with this PR is that it should use a templating system to generate code. And tests are missing to see if the annotation processor generates the right code. You can use "compile testing" or truth from Google for that. |
this.injectionMap = injectionMap; | ||
} | ||
|
||
String getFqcn() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FQCN
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comes from existing code
Pleased to see this getting some attention. I'll try to put some time into a review as well. |
Thanks @stephanenicolas and @johncarl81! |
I am reviewing the PR again. Here is the TODO list : (after talking with @Macarse, héhé, we work together)
|
@stephanenicolas The test for the last is in the sample module - https://github.com/f2prateek/dart/blob/master/dart-sample/src/test/java/com/f2prateek/dart/example/SampleActivityTest.java |
Thx @f2prateek . I am gonna work on that today.
WDYT ? |
I think it's useful to have this feature, but I agree there should be a way to seperate the binding features from the factory features. I had considered two ways to do this.
I'm in favour of the latter, seems like there is much less ceremony around it. |
Hi @f2prateek , thanks for your kind answer. From a user / dev perspective, I think solution 2 is really error prone : you have to annotate a class to get a behaviour.. But if you really consider this feature is not part of the core of Dart (and to my mind this can be defended, I would say it is just a different aspect of Dart), we should split the library. I mean either split in a different library project with its own repo or as a new module in dart. But the best to enable/disable the feature would be to add or not a dependency to your build, as a dev. But I think we might actually be over designing, to me it's quite possible that this is just a core Dart feature, just another aspect of extra injection. |
sorry for the multi builds, I was blind, There was a problem in my pom files about the plugin (android maven plugin being differnt in parent and pom, not taking into account the groupId change). Next commit is good. |
@f2prateek This commit should be green. Everything works locally. So we :
|
@@ -36,7 +36,6 @@ | |||
<dependency> | |||
<groupId>org.parceler</groupId> | |||
<artifactId>parceler-api</artifactId> | |||
<version>0.2.6</version> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldn't be hardcoded here.
@johncarl81 @f2prateek: Can you guys review? |
|
||
<dependency> | ||
<groupId>com.squareup</groupId> | ||
<artifactId>javapoet</artifactId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this absolutely required? Since Dart doesn't have seperate artifacts for the annotation processing and runtime API, we don't want to add these dependencies to the the user's app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, are there any class required at runtime in Dart? Could you just make all of Dart provided
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@johncarl81 , yes Dart as some class used at runtime. Namely, users must call Dart.inject(context)
to invoke that has been generated during annotation processing.
@f2prateek , the intent builder's code generation is much simpler with this dependency.
We could remove it for sure, but we would loose quality and maintenance comfort.
We can try the provided scope, it should work according to http://docs.codehaus.org/display/MAVENUSER/Dependency+Scopes
But maybe a better solution would be to separate runtime and compiler artifacts. Btw, @f2prateek , I thought you relied on proguard to remove the Dart annotation processor from final apk. And the same reasoning would have applied to any dependency here. But how does Dart annotation processor avoid getting included in final apk and not this dependency, so ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't use proguard, which is why the goal was to make the code generation part free of dependencies.
I'm not entirely sure provided would work here, since the annotation processing happens when a user includes the dart jar in their classpath. By marking javapoet as provided, javapoet won't be available on the classpath when the user is compiling their app.
I'm also working on splitting the artifacts for v2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we agree on either first splitting the artifacts or accepting the PR
with JavaPoet as a dependency ?
@f2prateek ?
2015-05-16 12:18 GMT-07:00 Prateek Srivastava notifications@github.com:
In dart/pom.xml
#33 (comment):@@ -35,6 +35,18 @@
compile-testing
test
<groupId>org.parceler</groupId>
<artifactId>parceler-api</artifactId>
<scope>test</scope>
<groupId>com.squareup</groupId>
<artifactId>javapoet</artifactId>
I don't use proguard, which is why the goal was to make the code
generation part free of dependencies.I'm not entirely sure provided would work here, since the annotation
processing happens when a user includes the dart jar in their classpath. By
marking javapoet as provided, javapoet won't be available on the classpath
when the user is compiling their app.I'm also working on splitting the artifacts for v2
—
Reply to this email directly or view it on GitHub
https://github.com/f2prateek/dart/pull/33/files#r30463728.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for splitting apj/processor to avoid unnecessary runtime inclusions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting the artifacts will be part of a v2 release. I'll clean this up and drop and JavaPoet dependency for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will follow up on this at the end of the PR conversation.
In Transfuse I opted for mandatory extras to be handled as part of the first builder phase (in my case the constructor) then optional extras as optional methods in phase two. My idea of how this should work in Dart is like this: new SampleActivityIntentBuilder(context, requiredExtra1, requiredExtra2...)
.setOptionalExtra3(extra3)
.setOptionalExtra4(extra4); This makes it much less likely that the end user will miss a mandatory extra I like the null check on the extras druing the |
"import com.f2prateek.dart.InjectExtra;", // | ||
"public class Test extends Activity {", // | ||
" @InjectExtra(\"key\") String extra;", // | ||
"}" // |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although these may not compile successfully, why not store them as actual Java files? We could put them in a separate non-source path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we just applied the recipe of current dart code. But yeah, a file would sound great, but not in this PR.
@johncarl81 about the constructor pattern : We would have to all agree on the API before we change something like that. |
final String statement; | ||
final TypeName fieldType; | ||
if (fb.isParcel()) { | ||
statement = "this.$N = org.parceler.Parcels.wrap($N)"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is great feature.
@stephanenicolas, Yes, I prefer compile time errors over runtime errors where possible. You could use Javadocs and parameter names to help with knowing what parameters are which. |
@johncarl81 me too I must say, but still, I don't like to have to pass all params in one method call. If we target that for a next release then our current implementations is probably a good basis for a first shot. |
Here is more or less what could the DSL generator look like. Indeed, it may not be so hard to implement : //the real intent builder would actually
//define a constructor with a context
//intent is a fake class below
public class IntentBuilder {
private Intent intent = new Intent();
//starting point
public AfterSettingA withA(A a) {
intent.putExtra(a);
return new AfterSettingA() {};
}
//intermediary states for mandatory fields
//one per field
public class AfterSettingA {
public AllSet withB(B b) {
intent.putExtra(b);
return new AllSet() {};
}
}
//final state, also allows to use optional fields.
public class AllSet {
//one method per optional field, same return type
public AllSet withC(C c) {
intent.putExtra(c);
return this;
}
//final method
public Intent build() {
return intent;
}
}
} |
@stephanenicolas, I have to say I like this approach. This has the benefit of clearly asking for each parameter by name while leveraging compile time to enforce required fields. One nit, I'd make sure to do a null check in each required DSL setter: //starting point
public AfterSettingA withA(A a) {
if(a == null){
throw new IllegalStateException("Parameter a is mandatory");
}
intent.putExtra(a);
return new AfterSettingA() {};
} |
@f2prateek : Follow up on the v2 idea and removing javapoet. Ok. Good for me. I think it is for @Macarse as well. So, you take it, right ? For the V2, chances are that we contribute. The best would be to have
Actually, in a v2, would you mind to rename the intent builder to 'Henson' ? I had this idea in mind a long time ago of creating an annotation processor to generate a navigation sub-layer between activities : https://github.com/stephanenicolas/henson. I never had time to code it, it was intended to work with the byte code weaving InjectExtra equivalent of Dart I created last year, but I am happy to participate to coding it in Dart. However I find the name is nice and for good reasons. Do you mind ? |
@johncarl81 we should double check with current optional / nullable contract of Dart for that. I didn't follow the latest changes. Wow, guys, we got a lot of features for a V2 here, but it really seems a lot for a PR ! Should we create a new V2 milestone, create a branch, and starting issuing tickets and coding ? Btw, I would be glad to join the contributors' team if that's possible. |
status? |
@Macarse I'm working on removing the JavaPoet dependency. |
Hi @f2prateek , do you have any progress ? We are really looking forward to this feature. |
This is just a first approach to issue #13. @stephanenicolas and I were discussing how to this for some time so I gave it a shot. It's far from finish but I would like to have some feedback.
Instead of a factory I used the information gather by dart to create a separate class which works as an intent builder.
In our app we are trying to get rid of the
IntentFactory
pattern and let every activity be responsible of it's API via a builder. We hope we can make Dart take care of that.Some open questions:
ExtraInjection
has aSet<FieldBinding>
instead of a single one. Why is that?IntentBuilder
to get information fromExtraInjector
? I am not very happy with the getters added