Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
PM 2Ring
Posts: 3713
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Sun Aug 12, 2012 9:06 am UTC

sourmìlk wrote:
PM 2Ring wrote:Good call, sourmìlk.

If you say so. Honestly, for a person whose job is development of web-based software, I haven't really touched javascript. I basically do everything server-side with C#* because I'm developing tools for internal use, and we don't need none of that fancy "updating without refresh" stuff everybody is always going on about.

* - For the record, though, I don't do that because I'm so in love with C#. It's a nice language, but the .NET libraries are horrible. I get the feeling that C# was designed by computer scientists rather than programmers.

On an unrelated note, I'm looking at GLM, and while they've done some cool things (like implementing swizzling), I can't get over how they did it. They hard coded all possible arrangements of vector elements when swizzling, and they could do this because they wrote separate classes for four separate vector sizes, and separate classes for various matrix sizes. I don't see how they can live with themselves. The ends do not justify the means!


You can do nice things with JavaScript, but unfortunately there's a lot of ugly JavaScript on the Web. Some of it's ugly because it uses some of JavaScript's more questionable features. But mostly it's ugly beacuse there are a lot of cargo-cult JavaScripters out there who create their code by cutting & pasting from dubious example code, with little understanding of what's going on. :)

As for C# and .NET, I know next to nothing about them, so maybe I shouldn't say anything... but I don't expect to see particularly good language design coming out of Microsoft: things like elegance and simplicity tend to suffer when they clash with Microsoft's philosophy of world domination. :)

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Steax » Sun Aug 12, 2012 9:36 am UTC

Javascript affords a huge level of usability, which then translates to efficiency. It's way faster to edit and auto-save an elastic list via Javascript than having to wait for load times, for example.

Of course, if you can control all the devices used, get bandwidth out of the way, and don't have time for JS...
In Minecraft, I use the username Rirez.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Sun Aug 12, 2012 9:39 am UTC

Elminster, when I can do pointer arithmetic in C#, and when it stops using a garbage collector, then you can say it's as low level as C++. I'm not saying that being at a higher level is necessarily worse. It's just different.

TheChewanater wrote:Well, their goal was to implement a particular subset of the GLSL specification, so I guess they had to. After all, the convenience of being able to use GLSL's semantics makes up for the inelegance of the implementation. (I say this after using GLM for a project where I had previously tried to write my own vector and matrix classes, which is not as fun as it sounds.)

I've had a ton of fun writing my own vector and matrix classes. I particularly liked that, due to C++'s awesome template system, you can make a matrix or vector of any size or type, and it checks for size and type compatibility at compile time.

As for swizzling: I'd have to think about it, but there has to be a better way to implement it than what they did. Maybe fucking with preprocessor defines or something. Though honestly, if it can't be implemented except for brute force, I'm going to just say it can't be implemented.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Sun Aug 12, 2012 5:30 pm UTC

You can do pointer arithmetic in C#, but you can't turn off the garbage collector.

As for C# and .NET, I know next to nothing about them, so maybe I shouldn't say anything... but I don't expect to see particularly good language design coming out of Microsoft: things like elegance and simplicity tend to suffer when they clash with Microsoft's philosophy of world domination. :)

I'm not sure what you're basing that on, because Microsoft hasn't designed many programming languages themselves. Of the ones that they have, they tend to be pretty good. VB was pretty bad (yet widely used), but VB.NET is quite pleasant. F# is an elegant functional language. In terms of paradigms, C# is similar to Java except it doesn't make you want to stab yourself in the eye with a rusty fork like Java does.

When it comes to development tools and platforms, Microsoft tends to be one of the best precisely because it's part of their world domination plan. Steve Ballmer didn't run onto the stage screaming "developers developers developers" for nothing you know. :lol:

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Sun Aug 12, 2012 6:12 pm UTC

PM 2Ring wrote:As for C# and .NET, I know next to nothing about them, so maybe I shouldn't say anything... but I don't expect to see particularly good language design coming out of Microsoft: things like elegance and simplicity tend to suffer when they clash with Microsoft's philosophy of world domination. :)

Actually, as imperative languages go, I'd definitely count C# among the top contenders. It's got a lot of things going for it. The .Net platform is also really nice from what I can tell. Like Sc4Freak, it's like Java, except... actually much better-designed. Except for the maddening capitalization conventions. :-) (It improves on or even downright fixes most or all of Java's biggest weaknesses, and then adds a bunch of additional benefits on top of it.) In terms of language and libraries, I don't think you get better than C#.Net for a GC'd imperative language. (Edit: first, due to my bias for GC, I'd drop the "GC'd" part of that qualification even. However, it occurs to me that I was ignoring some duck-typed languages like Python, so perhaps I'd state it as "I don't think you get better than C#.Net for a mostly-statically-typed, imperative language.")

To be honest, by far the biggest downside is the implementations. From what I can tell (I have not done anything approaching rigorous evaluations) the JVM is a better platform than the .Net VM, and Mono is a step down even from that. If those weren't true, I think I'd actually use it quite a bit.

User avatar
Shivahn
Posts: 2200
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: Coding: Fleeting Thoughts

Postby Shivahn » Sun Aug 12, 2012 10:52 pm UTC

Is there a nondeterministic Prolog variant, or a way to make it unpredictably go through its database?

I basically want to make a list of foods and their flavors, and then be able to ask it something like dinner(What) and get a result with a random appetizer, main course, and dessert that relate to each other in some way (for example, if the main course is savory, then the appetizer should not be primarily savory as well). I could do this in another language, but I want to practice Prolog, and it also seems like a Prolog-y problem.

User avatar
PM 2Ring
Posts: 3713
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Mon Aug 13, 2012 4:41 am UTC

Sc4Freak wrote:
As for C# and .NET, I know next to nothing about them, so maybe I shouldn't say anything... but I don't expect to see particularly good language design coming out of Microsoft: things like elegance and simplicity tend to suffer when they clash with Microsoft's philosophy of world domination. :)

I'm not sure what you're basing that on, because Microsoft hasn't designed many programming languages themselves. Of the ones that they have, they tend to be pretty good. VB was pretty bad (yet widely used), but VB.NET is quite pleasant. F# is an elegant functional language. In terms of paradigms, C# is similar to Java except it doesn't make you want to stab yourself in the eye with a rusty fork like Java does.

When it comes to development tools and platforms, Microsoft tends to be one of the best precisely because it's part of their world domination plan. Steve Ballmer didn't run onto the stage screaming "developers developers developers" for nothing you know. :lol:


Sorry, I was just having a bit of a rant. True, Microsoft hasn't designed many programming languages, but I've not been particularly impressed with their implementations of various languages. But I (mostly) based my previous comments on what I see as the Microsoft tendency to interpret standards in a non-standard way, eg how IE has traditionally handled HTML and JavaScript, and the abominable mess that Word tends to churn out when you save stuff as HTML.

As for their development tools, I haven't used them much, but they do seem to be awfully Microsoft-centric. I can't blame them for taking that approach, but it doesn't mean I have to be comfortable with it. :)

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Mon Aug 13, 2012 10:10 am UTC

Wow, you guys like the .NET libraries? I can't stand them: they're unpredictable and they violate basic rules of encapsulation by requiring the programmer to know the internal structure of the classes in order to use them. For example, I have to access rows in a System.Web.UI.WebControls.Table via the .Rows member. This is silly because I'm exposed to the internal storage of the table's rows, even though a table exists specifically to be a collection of rows. It's like if I had to access members of a C++ std::vector class with someVector.internal_array.
Last edited by sourmìlk on Tue Aug 14, 2012 3:53 am UTC, edited 1 time in total.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Steax » Mon Aug 13, 2012 10:33 am UTC

I think most developers are happy to overlook minor language design issues if they simply work. .NET has good adoption, works fairly well, and is well-supported by Microsoft.
In Minecraft, I use the username Rirez.

User avatar
Robert'); DROP TABLE *;
Posts: 730
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

Re: Coding: Fleeting Thoughts

Postby Robert'); DROP TABLE *; » Mon Aug 13, 2012 11:01 am UTC

sourmìlk wrote:Wow, you guys <i>like</i> the .NET libraries? I can't stand them: they're unpredictable and they violate basic rules of encapsulation by requiring the programmer to know the internal structure of the classes in order to use them. For example, I have to access rows in a System.Web.UI.WebControls.Table via the .Rows member. This is silly because I'm exposed to the internal storage of the table's rows, even though a table exists specifically to be a collection of rows. It's like if I had to access members of a C++ std::vector class with someVector.internal_array.

Are you sure? Table.Rows is listed as a property, so there's no guarantee that you're looking at the internal members.
...And that is how we know the Earth to be banana-shaped.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Mon Aug 13, 2012 5:14 pm UTC

Robert'); DROP TABLE *; wrote:
sourmìlk wrote:Wow, you guys <i>like</i> the .NET libraries? I can't stand them: they're unpredictable and they violate basic rules of encapsulation by requiring the programmer to know the internal structure of the classes in order to use them. For example, I have to access rows in a System.Web.UI.WebControls.Table via the .Rows member. This is silly because I'm exposed to the internal storage of the table's rows, even though a table exists specifically to be a collection of rows. It's like if I had to access members of a C++ std::vector class with someVector.internal_array.

Are you sure? Table.Rows is listed as a property, so there's no guarantee that you're looking at the internal members.

Yes, that's correct. Not only is it a properly, it returns a TableRowCollection - a custom collection designed specifically for this collection.

Perhaps ironically, the pattern that sourmilk is complaining about is common in .NET precisely because it hides implementation. The TableRowCollection's implementation is controlled by the library author. Internally, the Table class almost certainly has a container of some sort (List<TableRow> perhaps) which is wrapped by TableRowCollection. If the internal implementation of Table changes, then they are free to change the implementation of their list/collection without affecting the public interface. Obviously, if Table returned a List<TableRow> then that would break encapsulation... which is why they don't.

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Mon Aug 13, 2012 6:47 pm UTC

sourmìlk wrote:Wow, you guys <i>like</i> the .NET libraries? I can't stand them: they're unpredictable and they violate basic rules of encapsulation by requiring the programmer to know the internal structure of the classes in order to use them. For example, I have to access rows in a System.Web.UI.WebControls.Table via the .Rows member. This is silly because I'm exposed to the internal storage of the table's rows, even though a table exists specifically to be a collection of rows. It's like if I had to access members of a C++ std::vector class with someVector.internal_array.
I'm not sure what is bad about this? Tables are a lot more than just a set of rows, and you might want to be able to add/remove/modify rows? So short of adding all those methods to the table class (unless that's what you're suggesting?) they have to go somewhere?

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Aug 14, 2012 3:59 am UTC

Yes, and std::vectors are more than just arrays, but you don't need to access and alter the members of the internal arrays via someVector.internalArray because that's not encapsulation.

And returning a TableRowCollection does hide implementation, it exposes it. I shouldn't need to know that there's an internal TableRowCollection that's managing the collection of table rows.

Basically every time that a .NET class acts as a collection for something, I have to access a property that represents that internal collection. That's poor design.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Tue Aug 14, 2012 4:39 am UTC

sourmìlk wrote:And returning a TableRowCollection does hide implementation, it exposes it. I shouldn't need to know that there's an internal TableRowCollection that's managing the collection of table rows.

You don't know that. Perhaps there's a fresh TableRowCollection that is created each time which simply provides a view into the table class. And furthermore, even if there isn't, that's a change that they could make in the future, simply by giving you a new subclass or a new implementation of TableRowCollection. "They can change the implementation without changing the interface" certainly sounds like encapsulation to me.

Or put it in C++ terms. How do you return a character to an istream? (The iostream equivalent of ungetc.) Or determine how many characters are available to read? You have to go through the istream's streambuf object. Does istream::rdbuf break encapsulation because you have to know that there's an internal streambuf?

Edit: or you bring up std::vector as an example of something that's nice and encapsulated. The C++ standard comes very close to specifying how vector is implemented. Does the requirement that &v[0] is compatible with a C array break vector's encapsulation? After all, that requirement imposes way more of a restriction on how you can implement vector than "there is a Rows propertiy that gives you a TableRowCollection" does on Table.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Aug 14, 2012 8:27 am UTC

EvanED wrote:
sourmìlk wrote:And returning a TableRowCollection does hide implementation, it exposes it. I shouldn't need to know that there's an internal TableRowCollection that's managing the collection of table rows.

You don't know that. Perhaps there's a fresh TableRowCollection that is created each time which simply provides a view into the table class. And furthermore, even if there isn't, that's a change that they could make in the future, simply by giving you a new subclass or a new implementation of TableRowCollection. "They can change the implementation without changing the interface" certainly sounds like encapsulation to me.

But it's not good encapsulation because I still have to know that there's a separate member or property acting as internal storage, and use that and its methods. Why, as a user of the Table class, should I need to know that the Table class uses a TableRowCollection internally? I don't need to know that std::vector uses an array internally or whatever.

Or put it in C++ terms. How do you return a character to an istream? (The iostream equivalent of ungetc.) Or determine how many characters are available to read? You have to go through the istream's streambuf object. Does istream::rdbuf break encapsulation because you have to know that there's an internal streambuf?

Yes?

Edit: or you bring up std::vector as an example of something that's nice and encapsulated. The C++ standard comes very close to specifying how vector is implemented. Does the requirement that &v[0] is compatible with a C array break vector's encapsulation? After all, that requirement imposes way more of a restriction on how you can implement vector than "there is a Rows propertiy that gives you a TableRowCollection" does on Table.

Sure it places a restriction on how std::vector can be implemented, but who cares? As a user of the std::vector class, I certainly don't. I just like that, to use it, I don't have to know if there's an internal array or how or where it stores the data I want to access, I just have to ask for it.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Ubik
Posts: 1016
Joined: Thu Oct 18, 2007 3:43 pm UTC

Re: Coding: Fleeting Thoughts

Postby Ubik » Tue Aug 14, 2012 8:28 am UTC

What would then be your preferred way to handle a table and its rows?

User avatar
phlip
Restorer of Worlds
Posts: 7572
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Tue Aug 14, 2012 8:51 am UTC

Do you feel the same way about iterators? Like, say, in Java, where you have your List object, and then on that you call List.iterator() and get a magic internal sub-object that then has all the data within it in a nice iterable format. Surely we don't need to know that the List object is storing its data within iterators that way!

Or, to be more direct... this:
sourmìlk wrote:But it's not good encapsulation because I still have to know that there's a separate member or property acting as internal storage, and use that and its methods.
Is nonsense. The TableRowCollection object isn't necessarily what any given implementation is using to actually store the table rows... it's just your interface to that storage, wherever it might be. An implementation could have a main Table class that handles its stuff and a separate TableRowCollection class that does the storage, as you suggest... or it could store everything on the Table object directly, and then TableRowCollection is just a thin wrapper around that which pulls that data out in the appropriate way (as an iterator usually does). Or something else. It could very well be the case that if you never access the Table.Rows property, a TableRowCollection object will never be constructed in the lifetime of the Table. Or it could be an incredibly vital part of the whole deal. You don't know, and you don't need to know. So it is encapsulated properly.

Basically, I'm wondering... in what way does Table.Rows.Add() break encapsulation that, say, Table.AddRow() wouldn't? If every property and method on this TableRowCollection class was moved over to the main Table class (with an appropriate rename) it'd pass your encapsulation critereon. But you wouldn't have any more or less information about the actual implementation, and you'd still be able to do exactly the same things. It'd just be less convenient, because you wouldn't have this handy object that could implement all the various collections interfaces that TableRowCollection does.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Aug 14, 2012 12:00 pm UTC

Ubik wrote:What would then be your preferred way to handle a table and its rows?

Via methods in the Table class itself, just like std::vector or std::stack. Stack, for example, is a wrapper for (I think) std::vector, but I don't actually have to know that because I can just use pop() and push() and such.

phlip wrote:Do you feel the same way about iterators? Like, say, in Java, where you have your List object, and then on that you call List.iterator() and get a magic internal sub-object that then has all the data within it in a nice iterable format. Surely we don't need to know that the List object is storing its data within iterators that way!

No, the iterator is an entirely separate object that is sort of attached to the list. It's not a part of it. The analog isn't calling List.iterator(), it's called List.internal_array.

Or, to be more direct... this:
sourmìlk wrote:But it's not good encapsulation because I still have to know that there's a separate member or property acting as internal storage, and use that and its methods.
Is nonsense. The TableRowCollection object isn't necessarily what any given implementation is using to actually store the table rows... it's just your interface to that storage, wherever it might be. An implementation could have a main Table class that handles its stuff and a separate TableRowCollection class that does the storage, as you suggest... or it could store everything on the Table object directly, and then TableRowCollection is just a thin wrapper around that which pulls that data out in the appropriate way (as an iterator usually does). Or something else. It could very well be the case that if you never access the Table.Rows property, a TableRowCollection object will never be constructed in the lifetime of the Table. Or it could be an incredibly vital part of the whole deal. You don't know, and you don't need to know. So it is encapsulated properly.

It's encapsulated somewhat, just not ideally. I still know what it's using for internal storage and have direct access to that thing.

Basically, I'm wondering... in what way does Table.Rows.Add() break encapsulation that, say, Table.AddRow() wouldn't? If every property and method on this TableRowCollection class was moved over to the main Table class (with an appropriate rename) it'd pass your encapsulation critereon. But you wouldn't have any more or less information about the actual implementation, and you'd still be able to do exactly the same things. It'd just be less convenient, because you wouldn't have this handy object that could implement all the various collections interfaces that TableRowCollection does.

Yes, if every property and method were moved over to the Table class then that wouldn't be more encapsulated. But proper encapsulation doesn't expose all of the functions of the internal members. If the Table class wanted to expose all the functions of TableRowCollection, then it doesn't really have a TableRowCollection, it is one.

I guess .Rows is sort of just a hack around the lack of multiple inheritance. It's using composition where inheritance makes more sense.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: Coding: Fleeting Thoughts

Postby korona » Tue Aug 14, 2012 12:10 pm UTC

sourmìlk wrote:
phlip wrote:Do you feel the same way about iterators? Like, say, in Java, where you have your List object, and then on that you call List.iterator() and get a magic internal sub-object that then has all the data within it in a nice iterable format. Surely we don't need to know that the List object is storing its data within iterators that way!

No, the iterator is an entirely separate object that is sort of attached to the list. It's not a part of it. The analog isn't calling List.iterator(), it's called List.internal_array.

The same can be said about TableRowCollection. It is an entirely separate object that is sort of attached to the Table in order to let you access its data. You do not even know whether the data is really stored in TableRowCollection or if TableRowCollection is just an interface to a internal buffer. It is a perfectly fine example for abstraction because it does NOT expose the internal storage of the rows but rather gives you a generic interface to manipulate that storage. The actual table rows might be stored in a SQL database, on a different computer, on your harddrive etc. and you would not have to modify the code that uses the Table object.

EDIT: Inheritance only makes sense when you want to override virtual methods from the original object. Otherwise composition is better.

User avatar
phlip
Restorer of Worlds
Posts: 7572
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Tue Aug 14, 2012 12:35 pm UTC

sourmìlk wrote:Yes, if every property and method were moved over to the Table class then that wouldn't be more encapsulated.

But how? It would be functionally identical... there'd be nothing either you, or the library implementer, could do in one way that they couldn't do in the other.
sourmìlk wrote:But proper encapsulation doesn't expose all of the functions of the internal members. If the Table class wanted to expose all the functions of TableRowCollection, then it doesn't really have a TableRowCollection, it is one.

Still you keep talking like the mere existence of TableRowCollection makes it an "internal member" that's being exposed. Tell me. Which one of the properties/methods of TableRowCollection would you not want to have as a member of Table, if everything was moved across to there? Here, have a list.
sourmìlk wrote:I guess .Rows is sort of just a hack around the lack of multiple inheritance. It's using composition where inheritance makes more sense.

Whaaa...? What should be inheriting from what, exactly? I have no idea where you're going with this.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Tue Aug 14, 2012 1:20 pm UTC

As usual, everyone above (a few posts up) is saying "encapsulation" where they actually mean "implementation hiding". Encapsulation means something entirely different, i.e. "bundling things that are tightly related". The wrong use of the word is very widespread, it even appears in the GoF, but that doesn't mean we should stick to it.

I'm not saying this just to nag. Think about it. Encapsulation (in the real meaning of the word) is not a given; as an innovation it's at least as important as implementation hiding. We should honour the concept by not using its name for a different concept which already has a name of its own and is only vaguely related. Please spread the word!

Edit: typo.
Last edited by Jplus on Tue Aug 14, 2012 1:50 pm UTC, edited 1 time in total.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
phlip
Restorer of Worlds
Posts: 7572
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Tue Aug 14, 2012 1:25 pm UTC

You make a good point! My bad.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Tue Aug 14, 2012 4:59 pm UTC

sourmìlk wrote:But it's not good encapsulation because I still have to know that there's a separate member or property acting as internal storage, and use that and its methods. Why, as a user of the Table class, should I need to know that the Table class uses a TableRowCollection internally? I don't need to know that std::vector uses an array internally or whatever.

As myself and others have said, you don't know that:
Spoiler:

Code: Select all

$ cat test.cs
using System.Collections.Generic;

class TableRowCollection
{
    private Table the_table;

    internal TableRowCollection(Table table) {
        the_table = table;
    }

    public void Add(int i) {
        the_table.not_a_TableRowCollection.Add(i);
    }
}

class Table
{
    internal List<int> not_a_TableRowCollection = new List<int>();

    public TableRowCollection Rows {
        get { return new TableRowCollection(this); }
    }

    public void Print() {
        foreach (int i in not_a_TableRowCollection) {
            System.Console.WriteLine(i);
        }
    }
}


class Test
{
    static void Main()
    {
        Table t = new Table();
        TableRowCollection rows = t.Rows;
        rows.Add(1);
        rows.Add(2);
        rows.Add(3);       
       
        t.Print();
    }
}

$ gmcs test.cs
$ mono test.exe
1
2
3


Jplus wrote:As usual, everyone above (a few posts up) is saying "encapsulation" where they actually mean "implementation hiding". Encapsulation means something entirely different, i.e. "bundling things that are tightly related". The wrong use of the word is very widespread, it even appears in the GoF, but that doesn't mean we should stick to it.

That's a good point, though to be honest I do think it has a bit of a "there are two correct definitions and you're using one I don't like" flavor. (There are actually good reasons to want to keep them unambiguous of course, but I do think you can't say it's outright incorrect to use it in the information hiding sense.)

sourmilk, which definition of encapsulation are you asserting that Table breaks?

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Tue Aug 14, 2012 5:00 pm UTC

sourmìlk wrote:I guess .Rows is sort of just a hack around the lack of multiple inheritance. It's using composition where inheritance makes more sense.
I'm pretty sure it was a design choice, particularly for objects with multiple potential sub-item-lists. Like a DataTable, which has Columns, Contstraints, Rows, Relations, ect. You can either choose to show a list-like object for each, or implement the dozen or so methods each of them need directly on the DataTable. You could also just do the methods for the rows collection, but that means the interface is somewhat schizophrenic with regards to which collections you have to use a collection for, and which you have to use the parent object's methods to interact with.

Also, you can't really discern anything about a TableRowCollection other than it looks a lot like a list. It could have internal methods that call back into the Table, and vice versa, such as events for when data is modified/rows are added/ect. And all of that could change tomorrow without breaking the existing interface.

Ninja'd on the second part. :P

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Aug 14, 2012 9:02 pm UTC

I'm not sure I get why how TableRowCollection works matters here. Isn't the point that it's a member of Table that I can access without restriction enough to say that it violates principles of data hiding?
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

webzter_again
Posts: 119
Joined: Sun May 27, 2012 4:37 am UTC

Re: Coding: Fleeting Thoughts

Postby webzter_again » Tue Aug 14, 2012 9:11 pm UTC

sourmìlk wrote:Isn't the point that it's a member of Table that I can access without restriction enough to say that it violates principles of data hiding?


How can you access it without restriction?

What would a better implementation look like?

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Aug 14, 2012 9:16 pm UTC

webzter_again wrote:
sourmìlk wrote:Isn't the point that it's a member of Table that I can access without restriction enough to say that it violates principles of data hiding?


How can you access it without restriction?

There's a public get on the property.

What would a better implementation look like?

One in which the Table class had methods to access it restricted to the ones needed for using a Table. And if all the methods for TableRowCollection are needed for Table, why is TablerowCollection a separate class?
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Tue Aug 14, 2012 9:19 pm UTC

Code: Select all

#!/bin/bash
# Load definitions from the end of this source file
#
t=`mktemp`;cut -d"
" -f$(grep -n SHAZAAM $0 | tr \: \ | cut -f1 -d\ | tail -n1)- <$0>$t;source $t;rm $t

do_stuff


exit

#
# Under no circumstances must the word SHAZAAM occur below this line
#

function do_stuff {
  echo "Stuff"
}


Oh god, what have I created?
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Aug 14, 2012 9:26 pm UTC

If I knew shell script I could tell ya >.>

In an unrelated note, I hate when I'm at a part of a project where I'm too scared to move forward because I know it will involve some hellish debugging.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Tue Aug 14, 2012 9:44 pm UTC

sourmìlk wrote:
webzter_again wrote:
sourmìlk wrote:Isn't the point that it's a member of Table that I can access without restriction enough to say that it violates principles of data hiding?


How can you access it without restriction?

There's a public get on the property.

What would a better implementation look like?

One in which the Table class had methods to access it restricted to the ones needed for using a Table. And if all the methods for TableRowCollection are needed for Table, why is TablerowCollection a separate class?

Table (there are a few different ones we could be talking about) is already exposing a great many methods and properties. Encapsulation (as opposed to data/implementation hiding) means putting similar and related things together, and dissimilar things apart. Table, as a Control of some sort (depending on which namespace we're talking about), has information about rendering and interaction, and cares nothing of the data model. Encapsulation requires that the data implementation be kept separate from that, i.e., by putting it into a property.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Tue Aug 14, 2012 10:00 pm UTC

sourmìlk wrote:I'm not sure I get why how TableRowCollection works matters here. Isn't the point that it's a member of Table that I can access without restriction enough to say that it violates principles of data hiding?

:evil: It's not! Or at least, as I demonstrated, doesn't need to be to meet the documented interface (even though, to be fair, it probably is implemented that way).

Data hiding isn't just some buzzword you want because it sounds fancy. The reason you want it is because it will let you change out the implementation (in this case, of Table) without affecting the interface. Table's interface doesn't really violate that because new implementations can pick alternative implementation strategies (which is why my example and how TableRowCollection works is relevant, because it proves it).

I'm not saying that it's completely without its problems; in particular, it would be somewhat easy to write code that assumes that some_table.Rows == some_table.Rows is always true, in which case my implementation above will break that assumption, but even that can be worked around.

And the design has benefits. For instance, TableRowCollection implements IList, which means you can pass some_table.Rows to some function that wants an IList. It is a completely reasonable (and I'd argue good) tactic to not make Table itself implement that interface. In particular, there are at least three properties of Table that return a collection, and at least one more which would be pretty natural to add (columns). Which one is it going to use by default? Now, you could argue that .Rows is pretty natural to do by default, but "pretty natural" doesn't necessarily mean "the best choice". Personally, I'd rather see the proxy object.

Compare to two things in other programming languages. First is Python's dictionaries. There are at least three ways to iterate: over keys, over values, and over key,value pairs. Python's designers decided that by default, dictionaries should iterate over keys, but in my opinion it would be equally reasonable to decide that dictionaries should iterate over key,value pairs (after all, that's what's actually in the collection) -- and thus in my opinion, it would also be equally reasonable to decide that dictionaries shouldn't be iterable at all without being explicit about what you want. Now this analogy isn't very close, so let's go with something that's actually very good: Boost's bimap, which is like a bidirectional version of std::map. (I'll say it stores pairs made up of a left and a right. You can then look up a right value given a left one, or vice versa.) One way to implement this interface would be to make a class with left_to_right() and right_to_left() functions. And then you have a weird class that's sitting out there with its own API. But that's not what Boost did. Instead, a bimap object b has fields which you can access via b.left and b.right. You then say something like b.left[l] = r and then b.right[r] == l. And b.left and b.right are interface compatible with stl::map, which means that you can pass them to template functions which expect a map. That's good design, not bad! And it doesn't break information hiding: it tells me almost nothing about how bimap works internally. The only information I have about how bimap actually works is what I can infer from general data structure knowledge.

Ben-oni wrote:Table (there are a few different ones we could be talking about)

system.web.ui.webcontrols.table is what's under discussion, though I don't think that's been mentioned since the start of this topic.

Also, "Table, as a Control of some sort (depending on which namespace we're talking about), has information about rendering and interaction, and cares nothing of the data model. Encapsulation requires that the data implementation be kept separate from that, i.e., by putting it into a property." is a really good way of putting it.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Aug 14, 2012 11:29 pm UTC

The interface compatibility argument works pretty well for me. I just have one reservation:

The ease of changing implementation is just one of the reasons why data-hiding is good. Another is that it makes things simpler for the programmer using the module if he doesn't need to know about the internal workings.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Sizik
Posts: 1257
Joined: Wed Aug 27, 2008 3:48 am UTC

Re: Coding: Fleeting Thoughts

Postby Sizik » Wed Aug 15, 2012 12:55 am UTC

sourmìlk wrote:
webzter_again wrote:
sourmìlk wrote:Isn't the point that it's a member of Table that I can access without restriction enough to say that it violates principles of data hiding?


How can you access it without restriction?

There's a public get on the property.


Isn't that the point of a property?
she/they
gmalivuk wrote:
King Author wrote:If space (rather, distance) is an illusion, it'd be possible for one meta-me to experience both body's sensory inputs.
Yes. And if wishes were horses, wishing wells would fill up very quickly with drowned horses.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Wed Aug 15, 2012 1:10 am UTC

Sizik wrote:Isn't that the point of a property?

I think he's complaining that something that is a composition admits to being a composition.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Wed Aug 15, 2012 2:16 am UTC

Sourmilk, I'm surprised to hear you doubt that properties hide implementation. In the "Operator Overloading" thread, you seemed to be criticizing properties *because* they hide implementation (and thus have no time guarantees on access).

Anyway, properties decouple the access syntax of a class member and its implementation. If it's more intuitive and convenient to use "attribute" syntax, you can do so, even if the value returned must be computed (or if such computation may be required in the future). In short, properties remove the need for getters and setters.

Interestingly, one of Bertrand Meyer's principles of OOP is the "Uniform Access Principle", which states that all class members should be available through a unified access syntax, whether they are implemented by a method or an attribute. Properties don't fulfill the UAP strictly speaking, since there are still two syntaxes, but it comes close, since attribute syntax can be backed by either attributes or methods (via properties), while method syntax can be backed by (computational) methods or attributes in a method wrapper.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Aug 15, 2012 2:17 am UTC

Note that a property returning a particular interface is not a guarantee that there is an object in the class with that interface. The interface wrapper could have been created on the fly when you get the property.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

webzter_again
Posts: 119
Joined: Sun May 27, 2012 4:37 am UTC

Re: Coding: Fleeting Thoughts

Postby webzter_again » Wed Aug 15, 2012 3:00 am UTC

sourmìlk wrote:
webzter_again wrote:
sourmìlk wrote:Isn't the point that it's a member of Table that I can access without restriction enough to say that it violates principles of data hiding?


How can you access it without restriction?

There's a public get on the property.


But you can't access it without restriction. It has a public getter which returns a well-defined API which allows certain operations on a collection. Specifically, it's a strongly typed collection which was the vogue .net thing back 8 years ago.

I wouldn't say it's the pinnacle of good API design... but, if I was still using it then that would mean that I'd likely also still be programming in asp.net webforms and I'd probably have much, much bigger things to complain about.

User avatar
PM 2Ring
Posts: 3713
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Wed Aug 15, 2012 6:17 am UTC

You, sir, name? wrote:

Code: Select all

#!/bin/bash
# Load definitions from the end of this source file
#
t=`mktemp`;cut -d"
" -f$(grep -n SHAZAAM $0 | tr \: \ | cut -f1 -d\ | tail -n1)- <$0>$t;source $t;rm $t

do_stuff


exit

#
# Under no circumstances must the word SHAZAAM occur below this line
#

function do_stuff {
  echo "Stuff"
}


Oh god, what have I created?


You're a very naughty boy! :)

sourmìlk wrote:If I knew shell script I could tell ya >.>

Spoiler:
The script basically reads its own source and copies the stuff below & including the last line which contains SHAZAAM to a temporary file. It then proceeds to execute the copy in the same shell context that the script itself is running in, and then deletes the temporary file. So when the original script calls the do_stuff function it's the new version that gets executed.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Wed Aug 15, 2012 7:04 am UTC

You, sir, name? wrote:

Code: Select all

#!/bin/bash
# Load definitions from the end of this source file
#
t=`mktemp`;cut -d"
" -f$(grep -n SHAZAAM $0 | tr \: \ | cut -f1 -d\ | tail -n1)- <$0>$t;source $t;rm $t

do_stuff


exit

#
# Under no circumstances must the word SHAZAAM occur below this line
#

function do_stuff {
  echo "Stuff"
}


Oh god, what have I created done?

You've done a lot of work to get a line number is what. And worse, you didn't even check to see if mktemp already exists!

User avatar
PM 2Ring
Posts: 3713
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Wed Aug 15, 2012 8:08 am UTC

Ben-oni wrote: And worse, you didn't even check to see if mktemp already exists!

Um, that's `mktemp`, i.e., he's getting a new temporary file by running the mktemp command and saving its name into t.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 6 guests