-
Notifications
You must be signed in to change notification settings - Fork 169
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
Code-Free Constructor Violations #1468
Comments
@StuporHero even though the intention is good, we won't support this for two reasons:
Not also that in practice, using a scalar or a code free constructor won't change the overall design of those classes, so it's not worth the effort to do so just for the sake of doing it. That being said, let's not close this ticket right away, maybe some nice idea will come later on how to handle this situation in a nicer way! Thanks |
@victornoel I don't understand the point about envelopes not dealing with |
@StuporHero envelopes takes an instance of the interface they implement. If they start taking scalars, then they will have to call value() in their constructors: then you will not have code free constructors in envelopes! |
@victornoel You wouldn't have to call |
@victornoel Also, it is conceivable that an |
@StuporHero concerning iterable, you can use IterableOf if your want to define an actual behaviour to generate values. Iterable is not a data structures interface but a real object oriented one, that's why we have a bunch of decorators for it. |
@victornoel You're conflating the use of The only issue that looks like
We can safely reintroduce |
@StuporHero I think maybe you read them too fast, because there are two concerns with the old envelopes and they were well explained in those issues. I know because I wrote them, I designed and organized their applying in cactoos and also implemented some of those issues myself. There was the extra functionality, but there was also the laziness of using scalar. If we take for example the Set interface (it is the same for all concrete collections, list, map, set, etc, but not iterable or iterator!):
If you desire to have this behaviour, it is possible to make a new class LazySet that implements Set. But envelopes are NOT about that at all. So let's say you have a requirement that is not answered by existing abstractions in cactoos: please describe it here and we can find a solution for it. But we won't reintroduce scalar in envelopes for sure. |
My code example also showed as much. This is not a real objection because I already provided this solution. The only way you could gather that I read through what you linked too quickly is that you are ideologically opposed to my suggestion and uninterested in critically examining your own position. I spent 2 hours not just reading the issues you linked but diving into the code to understand what the problems were and why the solutions fixed them. I also reread @yegor256's blog posts concerning envelopes to understand his motivation for coming up with the concept because I like to understand why I'm wrong and because you have so far failed to impart that understanding at either the philosophical or practical level. This was all to ensure that I provided a carefully considered and thoughtful response to which I received this lazy slop. Give me a real, solid reason why |
@victornoel Here is direct evidence that you are patently wrong about not being able to use
|
@StuporHero before answering about cactoos, let me say something: we started on the wrong foot and it seems that the more you talk the more uncivil you are being. That being said, I'm still convinced the current design is the right decision, I will answer a bit later when I have time and I'm not being angry at the way this conversation went. |
@StuporHero so first: I disagree with @yegor256 in his video. The flexibility he talks about can be achieved in a much more simpler way than by having envelopes wrapping scalar and I am going to show you how, I hope you will see that my proposal (which is how it is implemented in cactoos) is equivalent but more simple and elegant. According to all this discussion and this video, I understand that the objective is to get the flexibility to choose WHEN the delegated object is created, and the argument is that by using scalar in the envelope, it allows to either choose a bare scalar or a sticky one (the "corner case" yegor talks about). I believe we can achieve the same like this: public interface SomeInterface {
void doA();
String someB();
public abstract class SomeInterfaceEnvelope implements SomeInterface {
private final SomeInterface wrapped;
public SomeInterfaceEnvelope(SomeInterface wrapped) {
this.wrapped = wrapped;
}
public void doA() {
wrapped.doA();
}
public String someB() {
return wrapped.someB();
}
}
public final class SomeImpl implements SomeInterface {
private final String txt;
public SomeImpl(String txt) {
this.txt = txt;
}
@Override
public void doA() {
System.out.println(txt);
}
@Override
public String someB() {
return txt.toUpperCase();
}
}
public final class IntImpl extends SomeInterfaceEnvelope {
public IntImpl(int value) {
super(new SomeImpl("" + value));
}
}
public final class LazySomeInterface implements SomeInterface {
private final Scalar<SomeInterface> wrapped;
public LazySomeInterface(Scalar<SomeInterface> wrapped) {
this.wrapped = wrapped;
}
@Override
public void doA() {
wrapped.value().doA();
}
@Override
public String someB() {
return wrapped.value().someB();
}
}
public final class RandomImpl extends SomeInterfaceEnvelope {
public RandomImpl() {
this(new Random());
}
public RandomImpl(final Random random) {
super(new LazySomeInterface(() -> new IntImpl(random.nextInt())));
}
}
} Here is what it allows:
Here is why it is better:
Concerning the specific case of Iterable, List and other classes in the collection package:
All of this stems from the following that is very important IMHO: most correctly designed object-oriented classes are already lazy by nature
|
@yegor256 as I said in telegram, it would be good to have your opinion about this architectural choice as your are the PO of Cactoos. I believe the previous comment is enough to cover the whole rationale of this choice. |
@victornoel Your reading comprehension skills are remarkably poor. The crux of this problem is that these classes do not follow EO guidelines in the library that claims to be built around EO. It's in the title of this ticket. You're attempting to argue that their current design is somehow preferable except that they now poison every constructor they are used in with code. There is no technical reason preventing the proper implementation, either. You told me to refer to @yegor256's blog to understand why you are right, and when I showed you the video attached to that blog making exactly the same argument I made to you, you said you disagreed with it. You can hold whatever opinions you like, but if I can't count on the EO library to comply with EO guidelines, there is no point in using it. I'd be better off forking it and maintaining a proper EO version for myself than wasting time talking to an ARC who is derelict in his duty to maintain this project according to its guiding principles. |
@StuporHero I'm sorry, but you crossed right now the line of healthy discussion. If you can't talk without offend other participants you're not welcome here. |
@fabriciofx Do you have an opinion on the issue being discussed? |
@StuporHero I read all arguments and I agree with @victornoel. You're free to disagree, we can be (Victor and I) both wrong, but ALWAYS be POLITE in a discussion, not matters what happens. |
@fabriciofx This all stemmed from @victornoel suggesting I read through things too quickly when I literally spent hours reading through the several links he sent as well as examining the source code and reading blog posts to try to understand why |
@victornoel I just looked at your code sample. If you want to keep the envelopes pure, that's fine, but understand that you need to use a lazy implementation in 100% of the constructors of classes that would otherwise require code in them in order for them not to violate the expectation established by the second principle linked in the README of this repository that all constructors in this library are code-free. Keeping the envelopes pure means you cannot use them for |
@StuporHero nothing justify someone to be disrespectful. If @victornoel was disrespectful with you, just say it and wait. I'm sure he will apologize. But you don't need to do in the same way, right? |
@fabriciofx I'm ready to get back to the topic of this ticket. |
@fabriciofx thank you for your mediation @StuporHero I'm sorry I offended you, English is indeed not my first language but anyway if I could have avoided it, I would have. That being said, you have been really rude repeatedly and again after I asked you to stop. Please do stop. Back to cactoos: let's not confuse the problem you raised and the solution you pushed for. I continue to think the current design in cactoos for envelope is the right one, and I already explained why. Concerning code free constructors, for now I consider them a necessary evil simply because I don't know how to avoid it except by deleting those classes. If you can propose a solution, please do so, but again let's stop confusing stuffs and please take the time to write organized and non-aggressive comments. |
After some thoughts and some discussion in telegram about the purpose of public static final ListOf<T> implements Scalar<List<T>> {
public ListOf(Iterable<T> iterable) {
this.iterable = iterable;
}
public List<T> value() {
List<T> list = new LinkedList<>();
this.iterable.forEach(list::add);
return list;
}
} This means you cannot use it like it is currently used via We would do the same for all the other implementation like this. WDYT @fabriciofx @StuporHero? |
@victornoel Stop saying things like, "let's not confuse the problem you raised and the solution you pushed for." THAT is rude and demonstrates that you don't understand what I'm asking for. I submitted an issue (there is code in some constructors), and I offered a possible solution (we could use Your currently proposed solution does not work because it would break a lot of code across many different libraries of my own. Why don't you just introduce the |
ListOf
,MapOf
, andSetOf
all contain some variation of a loop that assigns the values of thesrc
argument to the wrappedCollection
in their constructors. As I understand it, this is a violation of the Code-Free Constructor Principle. The fix is fairly straightforward and shouldn't affect users of these classes. The constructors forCollectionEnvelope
andIterableEnvelope
should be made to acceptScalar<Collection<T>>
andScalar<Iterable<T>>
respectively, and the action of adding the elements should be performed in a Lambda wrapped in aSticky<Collection<T>>
.The text was updated successfully, but these errors were encountered: