--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/2d748c33-31f2-4e17-b726-e2e17e198018%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Not quite, maybe…1 - one of the problem I often have ( solved by mixins and/or extension methods, delegation foo, and will also be solved by JDK8's default methods ) is when theres shared logic between two or three "similar" classes that for what ever reason cannot share a common parent class. You end up writing a whole of delegation methods and duplicating stub logic over the place.This then leads to the issue of any changes in that shared API, ripple out to any of the implementations offering stubs, which will make for extra pointless lines in a diff. Or, of those implementations are in separate artefacts, multiple diffs/commits/releases across all affected consumers - even if they don't need updating.
So not really laziness, but more just wanting to be tidy, or as you say - more elegant.2 - I see this quite similar to the above, if I have a method that returns an Int and the type is specified everywhere, if I can that to a Long then I also have to write commit/diffs containing every reference being changed. If however those return types are inferred by the compiler than _can_ ( not always mind you ) end up with a cleaner diff/change set only changing the definition - all the usages are unchanged.
3 - I can't actually recall what we said then, I'll have to go and revisit that. Hiding it behind the core system is wise yes, unless for whatever reason it's actually causing a manifestation IN the core system. I believe this was more talking about the general expression problem, and actually ties into hiding it away. The problem is introduced when you have components A and B which are separate artefacts, and isolated from each other, and you now have component C that wants to use A and B to talk to D. Sometimes it's more readable to consistently refer to the A and B objects with interface with D, but that can often mean that A and B need to implement an interface related to D so that they can be used. However, A and B have no reason of their own to know that D exists, so you really want to provide the implementation of D's interfaces for A and B, from the C module - enter type classes.
Again i would call this lazy because you should be returning a nice value class that has an int property. If you had used the value type everything would be clearer. Your use case of now requiring a long is a much simpler change. Again i see laziness as the motivation for not creating this nice value class because making the return type int is so much easier. Theres no need to bother the compiler at all and your programs are a zillion times more type safe. I think im write again :)
On 18/07/2013, at 8:16 PM, mP <miroslav...@gmail.com> wrote:Again i would call this lazy because you should be returning a nice value class that has an int property. If you had used the value type everything would be clearer. Your use case of now requiring a long is a much simpler change. Again i see laziness as the motivation for not creating this nice value class because making the return type int is so much easier. Theres no need to bother the compiler at all and your programs are a zillion times more type safe. I think im write again :)Just going to reply to this piece at the moment, I don't see how returning a value object containing an int, and switching to a value object containing a long is any different to the initial problem - at some point you're going to need to extract that int/long out of the value object to use it.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/bbfb5048-7189-4305-ba21-dab28b2c1a8f%40googlegroups.com.
On Jul 19, 2013 6:00 AM, "Richard Vowles" <ric...@bluetrainsoftware.com> wrote:
>The simple answer is just to have explicit saving. It makes things much more clear and much more elegant.
Isn't that the default when using JPA? Either way, I agree that implicit saving is extremely problematic.
No, implicit save happens if you are in a transaction, like it or not.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/CALa5nZxcS58RmuFECB22Oj5prAdQBTAEKP%2BZBmmL02spMF0KXQ%40mail.gmail.com.
So basically you agree that Hibernate should be using classes that never escape that layer. You copy from your model to the hibernate one do your stuff in an tx and thats it. Im saying you shoould never return anything touched, proxied or whatever by hibernate. No Hibernate/jpa/whatever annotations outside that layer. Only your service intf should ever be referenced by clients.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/d169f7b1-0461-430f-b04b-2422e7a1afc4%40googlegroups.com.
Actually, just adding Hibernate annotations doesn't mean the client needs them.If the annotations are not available on the class path then the JVM will (nicely, but also quite evilly) simply drop the annotation references from the loaded class and move on.Makes for some really fun code when you're doing isAnnotationPresent() on a class the was loaded whose class loader didn't have the annotation classes visible and you spend hours trying to track down why their not being found :)
Exactly why ask for mysterious problems to pop out and smack you in the head, when your busy with something else.
I have no idea why you would have a PatientDataTransferObject when you could just pass Patient. Seems pretty dumb.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/46e184c0-d790-4f2b-b2f7-a6c989306eba%40googlegroups.com.
@RobI clearly said and showed the reason for the separate Hibernate layer and its mapped value objects. Your example is contrived and stupid. I forgot to mention the obvious dumb thing that your clients now require HIbernate if you add Hibernate annotations and other crap onto the value type.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/0d1775bb-5096-4a7e-97a2-0d82478b6af6%40googlegroups.com.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/C6D1F21E-DD7F-4050-9B4D-F5AF697C037C%40talios.com.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/2d69e423-50ca-4bd4-a664-8823c5ef1547%40googlegroups.com.
Not quite, maybe…1 - one of the problem I often have ( solved by mixins and/or extension methods, delegation foo, and will also be solved by JDK8's default methods ) is when theres shared logic between two or three "similar" classes that for what ever reason cannot share a common parent class. You end up writing a whole of delegation methods and duplicating stub logic over the place.This then leads to the issue of any changes in that shared API, ripple out to any of the implementations offering stubs, which will make for extra pointless lines in a diff. Or, of those implementations are in separate artefacts, multiple diffs/commits/releases across all affected consumers - even if they don't need updating.So not really laziness, but more just wanting to be tidy, or as you say - more elegant.2 - I see this quite similar to the above, if I have a method that returns an Int and the type is specified everywhere, if I can that to a Long then I also have to write commit/diffs containing every reference being changed. If however those return types are inferred by the compiler than _can_ ( not always mind you ) end up with a cleaner diff/change set only changing the definition - all the usages are unchanged.
3 - I can't actually recall what we said then, I'll have to go and revisit that. Hiding it behind the core system is wise yes, unless for whatever reason it's actually causing a manifestation IN the core system. I believe this was more talking about the general expression problem, and actually ties into hiding it away. The problem is introduced when you have components A and B which are separate artefacts, and isolated from each other, and you now have component C that wants to use A and B to talk to D. Sometimes it's more readable to consistently refer to the A and B objects with interface with D, but that can often mean that A and B need to implement an interface related to D so that they can be used. However, A and B have no reason of their own to know that D exists, so you really want to provide the implementation of D's interfaces for A and B, from the C module - enter type classes.On 18/07/2013, at 3:23 PM, mP <miroslav...@gmail.com> wrote:Is it just me but all the complaints against java basically amount to laziness to type.1/There was an example base class that holds common properties. Sub classing is always done because were too lazy to make things more elegant. Today it might seem smart until a few months down the path, theres a big mess, because the base class has been used in logic etc to do stuff.2/Peter also was complaining about typing types and wanted the compiler to just know. Is this not lazyness again ? Too lazy to think and structure things properly so you hope it just works out and let the compiler guess. This of course works out until you need to refactor or change something and your in pain because there is no type info in the source.3/There was also another related example about introducing a dependency on some salesforce class or interface(cant recall which). Personally i think its almost always wrong to depend on 3rd party intf in a general case. They should be hidden away and never become part of the main core system. Shouldnt this be hidden away by a layer of indirection ? Is this is not lazyness in adding an interface belonging to the system and behind the scenes theres a Saleforce impl ?There were a few others, but i cant recalll them exactly, but im sure they were also products of basic laziness. Im not saying being lazy is wrong, im just trying to be fair in diagnosing the course and the effect.--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/2d748c33-31f2-4e17-b726-e2e17e198018%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/24EAB957-701B-4A88-BFF9-B5F0908678D7%40talios.com.
What I was meaning here, which may have not been clear is that in this project, at least in "my" mental variation of it, the situation is:- we've purchased and deployed mP's Patient Records System(tm), and we can't change that, without getting upstream/paid development.- we've found robsBmiCalculator on github/maven central and we wish to add BMI calculation/history for our patients, we can't change your code unless we fork the project, or submit a pull request and await a new release.- Neither mP's Patient System nor Robs BMI Calculator know about each other, and neither should they ever know about we otherIf Robs BMI calculator takes in (weight,height) as two Double values then we're all good, we can just simply call calBmi(weight,height), however if for what ever reason Robs BMI calculator declares the interface BmiLike which has getHeight/getWeight accessors, we need to create a bridge between mP's Patient class and something that implements BmiLike, since we can't alter the upstream class.In pseudo haskell, we could just declare an implement of BmiLike for Patient and move on:
instance BmiLike Patient p wheregetHeight = height pgetWeight = weight pand then just pass our patient instances to your function, which now implements the interface. Clojure provides a similar construct with its protocols, and scala has its type class pattern doing a similar thing.The whole specific example is somewhat contrived as I don't think you'd ever store a BMI directly on a Patient anyway, not as a direct value anyway, as height/weight changes over time any stored BMI reading as part of patient records would likely be stored as part of a timestamped diagnosis.I don't really see this as violating encapsulation, but more expanding modularity, if we were in control of the whole system, we could keep the separation of concern/modularity from the -definition- side of things, and keep the OO mental model on the implementation side using extension methods, so you could still call patient.calculateBmi() and feel all OO hipster if you like.After experimenting with Haskell and some other languages, that still do OO, but only... differently - in that they allow the operations on an class to be defined externally to the class itself is quite refreshing, and adds a hell of a lot of flexibility.By having BMI calcuations in terms of BmiLike's, you're encapsulating the BMI logic around BmiLike's, the fact that one either alters Patient to implement BmiLike and ties that class to an implementation ( which may, or may not be desired ), or one extends Patient to implement the interface ONLY where its needed is not really the concern of the BMI calculator.
On 21/07/2013, at 6:29 AM, Rob Lally <rob....@gmail.com> wrote:Separating the behaviour from the state here "robsBmiTool.calculateBmi(patient)" feels very un-object-oriented. I'm not opposed to that, I'm happy writing code in a functional style, but it doesn't fit very well with the whole purpose of the silly scheme - which was encapsulation. You've turned patient into a struct where all of the values need to be directly accessible.
--
---
You received this message because you are subscribed to the Google Groups "illegalargument" group.
To unsubscribe from this group and stop receiving emails from it, send an email to illegalargume...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/illegalargument/EB4DFFE1-D007-47A4-83D7-440D7A057C12%40talios.com.
On 20/07/2013, at 10:05 PM, mP <miroslav...@gmail.com> wrote:I have no idea why you would have a PatientDataTransferObject when you could just pass Patient. Seems pretty dumb.Well if Patient is the hibernate object, YOU don't want to pass that around :)
My example is exactly what *you* described - having separate classes for persistence and for general purpose use. And since mixing concerns would be bad, you then need all the mapping classes. If I wanted to be silly I could have created interfaces for all the classes. I also kindly skipped out data-store classes and interfaces because, frankly, I got tired of typing it. Yes it is dumb. Yes that was my point.And now with your demands for smaller value types you seem to want even more classes. I've already broken down all the numeric values into single classes, how much smaller should I make the classes? The PatientValue class only has two values and one derived value, how much smaller would you have that?
The clients don't require hibernate. As per your request to separate concerns, the *DataTransferObject classes have Hibernate annotations and the *Value objects have no annotations. Since this was your plan, I'm not sure why you are surprised by that.
I'm sure that there are times when that's the right choice, but most of the time when people create these sorts of systems it is because they are smart but bored by their environment and are trying to brighten up their day by over-engineering.