n2liquid's sandbox

Archive for the ‘Object-Orientation’ Category

Quick, what was the most important driving motivation behind object-orientation? Yeah, you got that right; it was that of creating a 1:1 relationship between software and the real-world problem-universe it had to deal with (I’m sure you knew this; if not, I’m not sure you’ll be much impressed with the rest of this post).

The big idea was that objects would map to real-world “things” (and classes would map to the concepts behind those things).

Crystal.

At first, it looks like object-orientation in languages like C++ and Java do this mapping really well. For example, you have “Car” classes representing what a car is (concept), and “Car”-type variables representing the different cars in your application (individual instances). That applies for anything: clients, bank accounts, users, blog posts, and so on.

Marvelous, ain’t it?

Kitsu Chiri burying Java engineers

I could go on on how interesting inheritance and subtype polymorphism is, and what expressiveness possibilities they grant to developers, but I don’t have much time, so let’s get straight to the point of this post:

Object-orientation as it is fails miserably to express many simple real-world systems because it is not thorough enough — it’s uneven.

Although we have means to outline concepts and instances, our ability to imbue their relationships in code is very limited. Inheritance isn’t a catch-all solution to describe relationships between objects like classes and objects are to package real-world stuff. Far!

Things can have different uses for different users. That’s why I came up with the users () specifier. With it, you can express in plain source-code that only Game Masters can kick or ban Players, for example. You get language support for that kind of thing.

There is another family of similar relationships that I’d like to see getting language support too, though.

Let’s keep the Game Master vs. Player example. Game masters are game masters no matter how you look at them. The same applies for players. But what about relative concepts? Two players can be friends and share a special API for friendly interactions. It’s like they implement a special interface (“Friend”), but only between themselves; only in-private.

Those relative concepts can currently be expressed in C++ by means of protected and private inheritance, but most people wouldn’t understand it because, at least as far as I know, the original intent of non-public inheritance wasn’t that of supporting this kind of thing.

C++’s protected and private inheritance usage “should not be seen as an IS-A relationship, but rather a HAS-A relationship“. As I see it, private inheritance can be used to build IS-A relationships. Private IS-A relationships, that is:

If I have a Friend reference to a Player called David, David IS-A friend for me. This isn’t composition, guys! I’ll call it a private relationship from here on.

Well, actually this is all a matter of how you see things: one could argue that David HAS-A Friend-type handle that it can let some others access. In fact, this is the correct interpretation of my example in the C++ world. But the point is, C++ has a feature that can be bended to make something useful (as I see it), and I wish I could have such a similar feature that allowed me to build private relationships without bending anything.

Another problem with the use of private inheritance to do this is that friends may not be friends forever (aah, the finity of all human things; that’s so sad).

How can you ensure that, once a friendship is broken in game, that’s reflected in code? Sure, you can write code to release the Friend handle, but that’s artificial: we want software to truly reflect our systems without us having to explicitly check stuff like we do today in Java, C++, and pretty much any other language.

Key here is that those languages widely are imperative, but their object-orientation constructs are declarative, and that’s what makes their expressiveness shine compared to languages like C. I want to extend object-orientation, as the largely useful declarative construct it is to map software to real-world systems, pushing it closer to those noble original intents, by declaratively covering a wider range of real-world relationships in software.

I think I’ve outlined an interesting solution to part of the problem in Public, Protected, Private, and Beyond, but unfortunately I’m quite clueless as to how to do the same with the private relationships I explained above. I’ll get back to this in a future post.

Hoping you’ve enjoyed the read. And always remember: Chiri doesn’t like uneven OOP/OOD and will react accordingly.

Advertisements

For some reason I don’t yet understand, there’s an abyssal segregation of object-oriented and generic code. I’m still to meet someone who wholeheartedly supports both.

The OOP folks think dynamic dispatches have negligible performance impact most of the time, which is undeniably true, so they really don’t care virtuals aren’t used in generic programming. Generic programming’s biggest raison d’être is “somewhat cool” at best for object-oriented heads.

On the other hand, the GP folks think dynamic dispatching is a useless feature that comes with a considerable performance penalty, which is also undeniably true (that is, sometimes the performance penalty is considerable; that’s not in contradiction with what I said earlier).

Dynamic dispatch has almost identical performance to direct calls, but is much slower compared to a small inlined function. Either way, these small penalties sum up a lot in some cases.

In general, GP is used for writing scientific simulation software, because the calculations are so massive and the overheads really sum up, and the gains of inlining become blatant.

loli haets 3d!

C++ is a programming language that supports OOP and GP, but separates them; they just don’t click together in this language.

One of the strenghts of generic programming is its support for duck typing, albeit only compile-time duck typing. At the same time, generic programming-based duck typing in C++ is one of its major pitfalls, because you don’t really have a choice not to use it.

There’s always been some tricks to put restrictions on types accepted by templates in C++, but they were all very far from perfect. For those curious, I think the best bet currently is to use C++11’s static assertions and type traits.

Concepts were proposed to give C++’s generic programmers the ability to formalize requirements and restrictions for template parameters, but the standards committee declined putting it into C++11 because, as far as I know, they wanted the idea to mature more. There are good chances that concepts will be introduced in a future iteration of C++.

The problem I see with concepts is that they’re essentially redesigned classes with a few additions. They’re calling it something new, but concepts are quite similar to classes. In the case of C++ there are (probably arguable) reasons for the insertion of concepts instead of making improvements to classes, so I wouldn’t set my word to stone that this would be the best for that language, but I’m pretty sure this could work amazingly well for Chii.

Later I’ll post the ideas I have for doing good OOP+GP, the Chii way.

I’d like to make a real quick introduction to Chii’s users () access specifier construct.

When defining who has access to which member of a class, the programmer can specify not only the traditional public, protected, or private specifiers, but also a list of classes. As a consequence, some aspects of a class will only be accessible by classes semantically related to them.

To illustrate, picture a class called GPUMemoryManager, and another one called GPUResource. Since GPUResources occupy GPU memory, it needs to ask the memory manager to allocate it.

In classical object-orientation, I can see this scenario solved in one of two ways: either the GPUMemoryManager allocates memory for anyone that asks it (e.g. it has a “public GPUBuffer allocate()” method), or it is embedded into GPUResources. Either way hurts encapsulation, since not everyone should be able to allocate GPU memory, and GPUResource shouldn’t have to deal with the internals of the allocation.

In Chii, the classes would be kept separate, and only GPUResources would be allowed to allocate memory through a well-defined interface:

class GPUAdapter
{
users (any): // alias: public
    construct() { ... }

users (GPUAdapter): // alias: protected
    void internalWork() { ... }

users (none): // alias: private
    GPUAdapterGuts mInternalData;

users (GPUResource): // something new!
    GPUMemory allocate(...) { ... }
}

This is similar to C++’s infamous “friend class” construct, but more restricted, in a way that helps encapsulation, while solving most of the problems it was intended to solve (in fact disallowing only the bad use cases of it, in which people would do perverted things with an object’s privates~).


Cute bouncing pixels

un.ma.i!

Twitter (technical)

Error: Please make sure the Twitter account is public.

Twitter (personal)

Error: Twitter did not respond. Please wait a few minutes and refresh this page.

Get messaged when I post something new!
Just enter your e-mail and hit Follow:

Join 171 other followers

%d bloggers like this: