Decapsulation



  • Per requirements, I built an object that contained a very complex series of data structures, and six public interface methods to manipulate them. There was also a simple DAO service that retrieved the pertinent data from the DB, and a business-layer service that provided encapsulated access to said object. This way, it would work as both a local object as well as via an EJB, and the location would be buried inside the service layer. Basic encapsulation of data and functionality.

    In a code review, I was questioned as to why all access went through the service layer. Encapsulation. No, we want to put the functionality to manipulate the raw data structures in each entity that needs it. But that would put the logic all over the place, lead to duplicated code and make maintenance difficult. We don't care; redo it.

    And so, the internal data structures are exposed to the world, and the logic of the 6 functions has been moved out of the object to wherever it was needed.

    I found out that this has been done in about 20+ other instances.

    Wheee!



  • I'm sorry for you !

    Do you work with people that have no brain function whatsoever ?

    But you can't deny that "Code duplication" is the greatest invention of the mankind since the "easy to store squared-wheel"



  • @snoofle said:

    In a code review, I was questioned as to why all access went through the service layer. Encapsulation. No, we want to put the functionality to manipulate the raw data structures in each entity that needs it. But that would put the logic all over the place, lead to duplicated code and make maintenance difficult. We don't care; redo it.

    Who's "we"? Do you have any clout to refuse their instructions?



  •  Upside: you can charge them up the wazoo for maintenance every time they want a change.



  • @da Doctah said:

     Upside: you can charge them up the wazoo for maintenance every time they want a change.


    Where did you get that dumb idea from? You can't "charge" your employer anything to maintain stuff that's your job



  • @Kyanar said:

    You can't "charge" your employer
     

    Unless you're a contractor.

    I don't know which snoofle is.



  • @dhromed said:

    @Kyanar said:

    You can't "charge" your employer
     

    Unless you're a contractor.

    I don't know which snoofle is.

    I am an hourly contractor. "We" are the two technical team leads at the company where I am contracting. The rule is that I am not allowed to extrapolate and do something along the lines of "I know what the specs meant to say so I will build what they want and not what they wrote"; I am required to take the written specs literally, which leads to all sorts of wtf's that I'll be posting at some point.

    In this case, these guys like to do things inside out and put the logic every place it's used (as opposed to "burying" it in a common utility object). The specs didn't go into the implementation of this particular object. They just want me to code in their "style".

    They pay the bills so I have to code stuff the way they want; so I made the changes. I figure that in about a month, there will be assorted enhancement requests forthcoming, and it will take 6-8 times longer to do it because of all of the code duplication.

    $profit!

     



  • @snoofle said:

    $profit!
     

     Yes, but what about your SOUL, man?



  • @dhromed said:

    @snoofle said:

    $profit!
     

     Yes, but what about your SOUL, man?

    You just summed up a longer reply I was going to make. I have been in the same position of having to build things the way the bill payer wanted them built, rather than building them in a "best practices" manner. After you do this enough times it does become soul destroying and the money matters less and less.



  • @dhromed said:

    @snoofle said:

    $profit!
     

     Yes, but what about your SOUL, man?

    I have worked on Wall Street for various banks and brokerages for 20+ years now. Almost everyone for whom I have worked has had that "I know how to do this better than everyone else because I'm smarter than they are" mentality. I learned a long time ago that if you take it personally, you die a little inside each time you encounter this stupidity. I choose to view it as a source of laughter (look at what these morons are asking me to do!). Once you make that leap, it's not so bad, and they are willing to pay you a king's ransom to give them what they want.

    I limit the workday to 8 hours (most folks on Wall St. work a standard 12 hour day with no overtime). I get paid very well for all the time that I work. And I have nearly non-stop on-site entertainment to keep me (and by extension, all of you) amused.



  • @snoofle said:

    and they are willing to pay you a king's ransom to give them what they want
    The trouble is that a lot of places want to spend the minimum amount of money to get the desired functionality and you don't have the luxury of making the tradeoff that you have.



  • @snoofle said:

    [...] they are willing to pay you a king's ransom to give them what they want.[...]

    I get paid very well for all the time that I work. And I have nearly non-stop on-site entertainment to keep me (and by extension, all of you) amused.

    You can't argue with a triple-win situation.



  • @OzPeter said:

    @snoofle said:
    and they are willing to pay you a king's ransom to give them what they want
    The trouble is that a lot of places want to spend the minimum amount of money to get the desired functionality and you don't have the luxury of making the tradeoff that you have.

    Don't get me wrong, these people are idiots; as long as they're willing to pay folks to work in the most inefficient way possible, I'm happy to take their money,

    Naturally, I'd prefer a position where they encouraged you to do things the best way possible, and I've worked for one or two folks who believed in and supported that, but for the most part, those positions don't generate a whole lot of fodder for this forum; you guys only hear about the stupid stuff I encounter.

     



  • @snoofle said:

    In this case, these guys like to do things inside out and put the logic every place it's used (as opposed to "burying" it in a common utility object)

    If you put all the code in one class you risk creating a God Object that contains all the shared logic of one particular aspect of the program. This way changes in one place have effects in other places and fixing one bug can create two more.

    In our app we have one such class that is 2,600 lines long and has 150 methods. Don't get me wrong, it does provide spectacular reusability, but changing it is like walking through a minefield. Unit test would help but, well, we don't unfortunately do that here; and maintenace of the unit tests would also not be trivial.



  • @snoofle said:

    I learned a long time ago that if you take it personally, you die a little inside each time you encounter this stupidity. I choose to view it as a source of laughter (look at what these morons are asking me to do!). Once you make that leap, it's not so bad
     

    You are a strong mind.

    Use this power for good.



  • @SlyEcho said:

    ...God Object...

    In general I agree.

    In this case, it was a self-contained series of transformation calculations on a particular data object. It doesn't make sense to copy the formulas to everyplace they're used, but that's what they wanted me to do.

    Rationale? When perusing the code in any given location, you can immediately see what it's doing. If the calcs are in another object, you need to click through to see what it's doing, and in so doing, you lose the context of what you were originally perusing.

     



  • @dhromed said:

    @snoofle said:

    $profit!
     

     Yes, but what about your SOUL, man?

    On a pragmatic level, if all they want is a robot who follows spec sheets literally and they don't give a crap about bad code, what stops them from calling up an outsourcing firm in India to do it? I mean, hell, you can get shitty code written anywhere for dirt cheap.



  • @snoofle said:

    If the calcs are in another object, you need to click through to see what it's doing, and in so doing, you lose the context of what you were originally perusing.
     

    It's the goldfish school of programming.



  •  @SlyEcho said:

    @snoofle said:
    In this case, these guys like to do things inside out and put the logic every place it's used (as opposed to "burying" it in a common utility object)

    If you put all the code in one class you risk creating a God Object that contains all the shared logic of one particular aspect of the program. This way changes in one place have effects in other places and fixing one bug can create two more.

    In our app we have one such class that is 2,600 lines long and has 150 methods. Don't get me wrong, it does provide spectacular reusability, but changing it is like walking through a minefield. Unit test would help but, well, we don't unfortunately do that here; and maintenace of the unit tests would also not be trivial.

     Not if you design everything around the idea of each class having one and only one purpose. If you notice some of the functionality of your class is outside of its initial scope, either figure out what its scope really is, or create a new class/figure out where the functionality really should be and handle the functionality the class needs, but is out of its scope, through containership, passing, or a singleton* approach.

     

     

    *I actually have very little experience with singletons, so I couldn't tell you if they're suicidal in the long run to large projects.



  • @SlyEcho said:

    If you put all the code in one class you risk creating a God Object that contains all the shared logic of one particular aspect of the program. This way changes in one place have effects in other places and fixing one bug can create two more.

    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.



  • @morbiuswilters said:

    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.

    Oh no! My God Object cannot save(), it can only store()!



  • @snoofle said:

    @dhromed said:

    @snoofle said:

    $profit!
     

     Yes, but what about your SOUL, man?

    I have worked on Wall Street for various banks and brokerages for 20+ years now. Almost everyone for whom I have worked has had that "I know how to do this better than everyone else because I'm smarter than they are" mentality. I learned a long time ago that if you take it personally, you die a little inside each time you encounter this stupidity. I choose to view it as a source of laughter (look at what these morons are asking me to do!). Once you make that leap, it's not so bad, and they are willing to pay you a king's ransom to give them what they want.

    I limit the workday to 8 hours (most folks on Wall St. work a standard 12 hour day with no overtime). I get paid very well for all the time that I work. And I have nearly non-stop on-site entertainment to keep me (and by extension, all of you) amused.

     

     I've done stuff that I know wasn't right and my soul cries a little each time.

    I've gotten to the point now where, though it still bothers me, I know it's not worth fighting over.



  • @SlyEcho said:

    @morbiuswilters said:
    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.

    Oh no! My God Object cannot save(), it can only store()!

    Obviously: if you want to save() you have to create a Messiah class that extends God and implements ICharitable.  Just be careful about importing it into the same namespace as Roman or SneakyJew, or you might just end up with a NailPointerException.



  • @morbiuswilters said:

    @SlyEcho said:
    @morbiuswilters said:
    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.
    Oh no! My God Object cannot save(), it can only store()!
    Obviously: if you want to save() you have to create a Messiah class that extends God and implements ICharitable.  Just be careful about importing it into the same namespace as Roman or SneakyJew, or you might just end up with a NailPointerException.
    The new version ("NT") of the God object has that built in: [code]God.getGod().getSavior().save(this);[/code]  (Supposedly that method was there all long, but it had private access.)

    Unfortunately, despite what published documentation says, there have been many reports that the NT version is not totally compatible with the old one.  Specifically, since the [code]acceptAnimalSacrifice()[/code] method has been deprecated, old code that relied on its side effects may break.



  • @SlyEcho said:

    @morbiuswilters said:
    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.

    Oh no! My God Object cannot save(), it can only store()!

    I hate it when people refer to it as the God Object, because it confuses the uneducated.  You should only refer to it by its proper name: the Higgs JSON.  Anyway, I thought we still hadn't found it.  Isn't that why they built that huge lab in Switzerland to smash copies of Design Patterns into one another?


  • @Xyro said:

    @morbiuswilters said:

    @SlyEcho said:
    @morbiuswilters said:
    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.
    Oh no! My God Object cannot save(), it can only store()!
    Obviously: if you want to save() you have to create a Messiah class that extends God and implements ICharitable.  Just be careful about importing it into the same namespace as Roman or SneakyJew, or you might just end up with a NailPointerException.
    The new version ("NT") of the God object has that built in: <font size="2" face="Lucida Console">God.getGod().getSavior().save(this);</font>  (Supposedly that method was there all long, but it had private access.)

    Unfortunately, despite what published documentation says, there have been many reports that the NT version is not totally compatible with the old one.  Specifically, since the <font size="2" face="Lucida Console">acceptAnimalSacrifice()</font> method has been deprecated, old code that relied on its side effects may break.

    Yeah, but there are a lot of third-party proxies for the NT version, and they all have different interfaces.  For example, LutherSoft put out their own version due to a variety of complaints with the de facto version.  I won't go into a lot of detail, but a lot of it had to do with the resources taken by the proxy when blessing other objects.  Since then, a lot of different implementations have popped up with differences ranging from whether or not objects are considered dirty at creation all the way up to whether or not the God Object is three objects, one object, or three interfaces to one object.  There are some really crackpot ones out there, too, like the one that handles Pythons.


  • @Xyro said:

    @morbiuswilters said:
    Obviously: if you want to save() you have to create a Messiah class that extends God and implements ICharitable.  Just be careful about importing it into the same namespace as Roman or SneakyJew, or you might just end up with a NailPointerException.
    The new version ("NT") of the God object has that built in: <font size="2" face="Lucida Console">God.getGod().getSavior().save(this);</font>  (Supposedly that method was there all long, but it had private access.)
     

    Doesn't the NT version have a GodFactory.getNewGod() anymore? That usually solved things with Egyptian or Roman.

     



  • @bstorer said:

    @Xyro said:

    @morbiuswilters said:

    @SlyEcho said:
    @morbiuswilters said:
    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.
    Oh no! My God Object cannot save(), it can only store()!
    Obviously: if you want to save() you have to create a Messiah class that extends God and implements ICharitable.  Just be careful about importing it into the same namespace as Roman or SneakyJew, or you might just end up with a NailPointerException.
    The new version ("NT") of the God object has that built in: <font face="Lucida Console" size="2">God.getGod().getSavior().save(this);</font>  (Supposedly that method was there all long, but it had private access.)

    Unfortunately, despite what published documentation says, there have been many reports that the NT version is not totally compatible with the old one.  Specifically, since the <font face="Lucida Console" size="2">acceptAnimalSacrifice()</font> method has been deprecated, old code that relied on its side effects may break.

    Yeah, but there are a lot of third-party proxies for the NT version, and they all have different interfaces.  For example, LutherSoft put out their own version due to a variety of complaints with the de facto version.  I won't go into a lot of detail, but a lot of it had to do with the resources taken by the proxy when blessing other objects.  Since then, a lot of different implementations have popped up with differences ranging from whether or not objects are considered dirty at creation all the way up to whether or not the God Object is three objects, one object, or three interfaces to one object.  There are some really crackpot ones out there, too, like the one that handles Pythons.

    You fucking win.



  • @b_redeker said:

    @Xyro said:
    @morbiuswilters said:
    Obviously: if you want to save() you have to create a Messiah class that extends God and implements ICharitable.  Just be careful about importing it into the same namespace as Roman or SneakyJew, or you might just end up with a NailPointerException.
    The new version ("NT") of the God object has that built in: <font face="Lucida Console" size="2">God.getGod().getSavior().save(this);</font>  (Supposedly that method was there all long, but it had private access.)
    Doesn't the NT version have a GodFactory.getNewGod() anymore? That usually solved things with Egyptian or Roman.
    Officially no, but it's still accessible via reflection. However, since it doesn't support the NT version, its God objects returns null for the getSavior() method. (Same problem with deserialized instances of the old version.)  Officially, it's only accessible via the singleton getGod() assessor, but, as bstorer mentioned, there are three internal views that extend God and expose different methods. Some proxies treat those views as distinct objects, thus refuting the singleton pattern.  Shrug.  Here's to hoping the next version has better documentation.



  • @snoofle said:

    No, we want to put the functionality to manipulate the raw data structures in each entity that needs it. But that would put the logic all over the place, lead to duplicated code and make maintenance difficult. We don't care; redo it.
    I've spent the last 3 weeks rewritting a car accident of a system into (semi) decent OO code. Analyze, design, write proof-of-concept code, refactor, analyze, design, and so on and so forth. 

    What you wrote actually made me a little sick. 



  • @bstorer said:

    a lot of it had to do with the resources taken by the proxy when blessing other objects

    Wait, this is a Perl library? That explains a lot.



  • @toth said:

    @bstorer said:
    a lot of it had to do with the resources taken by the proxy when blessing other objects

    Wait, this is a Perl library? That explains a lot.

    Oh, wow!  What a funny coincedence!  I totally didn't think of that and it definitely wasn't the point of that sentence at all! Hey, I just realized that Python is an actual programming language, too!  It's almost like these puns were intentional!  Surely that can't be it, though.



  • @bstorer said:

    @toth said:

    @bstorer said:
    a lot of it had to do with the resources taken by the proxy when blessing other objects

    Wait, this is a Perl library? That explains a lot.

    Oh, wow!  What a funny coincedence!  I totally didn't think of that and it definitely wasn't the point of that sentence at all! Hey, I just realized that Python is an actual programming language, too!  It's almost like these puns were intentional!  Surely that can't be it, though.

    Hey, I'm here to help.



  • @bstorer said:

    @toth said:

    @bstorer said:
    a lot of it had to do with the resources taken by the proxy when blessing other objects

    Wait, this is a Perl library? That explains a lot.

    Oh, wow!  What a funny coincedence!  I totally didn't think of that and it definitely wasn't the point of that sentence at all! Hey, I just realized that Python is an actual programming language, too!  It's almost like these puns were intentional!  Surely that can't be it, though.

    This might just be a crazy guess, but am I detecting a bit of... sarcasm?



  • @blakeyrat said:

    This might just be a crazy guess, but am I detecting a bit of... sarcasm?
    Oh, no, that's sandalwood.  It's my new cologne, Eau de Sardonique.



  • @toth said:

    Wait, this is a Perl library?

    Well, those Perl monks are very devoted.

    Anyway, I was thinking of switching to some Eastern language like Ruby. I hear that they don't have any god objects at all and garbage collection infinitely reuses objects. This applies to everything as everything is an object. Think about that the next time you throw away a return value or split a string, it might come back as a ChildNode or NextSibling object later.

    Also there's persistance to the cloud, you have to call the method ten times during the object's lifetime and that's all you have to do! But others criticize this feature saying that the cloud storage is seemingly write-only and the APIs to access the cloud resemble god objects themselves.



  • @Xyro said:

    Shrug.  Here's to hoping the next version has better documentation.
    Yeah, the last documentation was a mess. Besides being of biblical proportions, it had lots of ambiguous and conflicting information. At least its chapters were decently numbered for quick reference.



  • @Zecc said:

    Yeah, the last documentation was a mess. Besides being of biblical proportions, it hads lots of ambiguous and conflicting information. At least its chapters were decently numbered for quick reference.
    Like that "do not free objects, ever" clause, but a bnch of examples involve lots of freeing of objects and there's even a "free all witch-objects ASAP" clause. Then there's "Don't do inheritance without concent", then this one example is all like "Inherit this object", "I don't have concent guy", "Inherit this object", "That's my brother's wife guy", "Inherit this object", objector dumps state on the ground, "You suck. Delete."



  • @bstorer said:

    @Xyro said:

    @morbiuswilters said:

    @SlyEcho said:
    @morbiuswilters said:
    But then we'll have a God Object who can use his magic powers to save us* and everything will be perfect forever.
    Oh no! My God Object cannot save(), it can only store()!
    Obviously: if you want to save() you have to create a Messiah class that extends God and implements ICharitable.  Just be careful about importing it into the same namespace as Roman or SneakyJew, or you might just end up with a NailPointerException.
    The new version ("NT") of the God object has that built in: <font face="Lucida Console" size="2">God.getGod().getSavior().save(this);</font>  (Supposedly that method was there all long, but it had private access.)

    Unfortunately, despite what published documentation says, there have been many reports that the NT version is not totally compatible with the old one.  Specifically, since the <font face="Lucida Console" size="2">acceptAnimalSacrifice()</font> method has been deprecated, old code that relied on its side effects may break.

    Yeah, but there are a lot of third-party proxies for the NT version, and they all have different interfaces.  For example, LutherSoft put out their own version due to a variety of complaints with the de facto version.  I won't go into a lot of detail, but a lot of it had to do with the resources taken by the proxy when blessing other objects.  Since then, a lot of different implementations have popped up with differences ranging from whether or not objects are considered dirty at creation all the way up to whether or not the God Object is three objects, one object, or three interfaces to one object.  There are some really crackpot ones out there, too, like the one that handles Pythons.
     

     

    Well, y'know, unless God's a singleton with all static instance members, we could do this for the lulz:

     

    God cthulu=new God("Eldritch Abomination");

    cthulu.doRARGRBLARGRBLAGLECTHULUSEATINGMYSOULBECAUSEITRIEDTOTELLHIMWHATTODORBLAGRBLAGRAGAG();



  • @SlyEcho said:

    @snoofle said:
    In this case, these guys like to do things inside out and put the logic every place it's used (as opposed to "burying" it in a common utility object)

    If you put all the code in one class you risk creating a God Object that contains all the shared logic of one particular aspect of the program. This way changes in one place have effects in other places and fixing one bug can create two more.

     

    This kind of reply pisses me off to no end. You have officially won my douche bag award of the year.



  • @JohnWestMinor said:

    Well, y'know, unless God's a singleton with all static instance members, we could do this for the lulz:

     

    God cthulu=new God("Eldritch Abomination");

    cthulu.doRARGRBLARGRBLAGLECTHULUSEATINGMYSOULBECAUSEITRIEDTOTELLHIMWHATTODORBLAGRBLAGRAGAG();

     

    Better wrap this in a try {} catch (EvilDaemonException){} because I've seen some ugly stuff reported with this.


Log in to reply