PDA

View Full Version : New language features have a place in game code?



WILL
23-03-2012, 08:08 PM
Hey everyone, I'm just wondering with all these new language features appearing in the new Oxygene language and future versions of Delphi and other Object Pascal based tools, is there a place or a purpose for them in game code? What types of game engine systems or features could be enhanced by using these types of language features in your code?

Off-hand here is a short list of the newer features I can think of: (in no intended order of importance or indication of usefulness)

Generics
Duck Typing
Oxygene's await keyword
nested classes
for .. in loops
final methods


What are your thoughts or experiences with any of these or other new language features? Did I miss any major ones?

Super Vegeta
23-03-2012, 10:47 PM
Generics are obviusly very useful for saving the trouble of copy-pasting code that is exactly the same in function, but intended to be used with different types. Operator overloading allows to write shorter code (although sometimes the overloads can be vague and not so obvious if one looks at the code after a long time).

LP
24-03-2012, 01:12 AM
Operator overloading and "for...in" loops are huge space/time savers and help to improve the readability of your code.

However, I would advise to stay away from using generics. In most situations they are time savers on short-term, but they actually hurt the readability of the code and indirectly reduce non-functional quality attributes of the software you are working on. I personally avoid them like a plague.


Generics are obviusly very useful for saving the trouble of copy-pasting code that is exactly the same in function, but intended to be used with different types.
I don't agree. You can avoid copy-pasting by using refactoring properly, with the common techniques like class inheritance (http://en.wikipedia.org/wiki/Class_inheritance) among others. Using generics is mostly a quick and dirty (http://en.wikipedia.org/wiki/Quick-and-dirty) approach to a problem, so that you can quickly achieve something without proper architectural design and ignoring any existing software design patterns (http://en.wikipedia.org/wiki/Software_design_pattern) that may apply.

I think generics were introduced to Pascal languages for marketing reasons, they were not really necessary. This is a similar issue to exceptions. I also rarely use exceptions myself and consider them unnecessary, similar to Joel Spolsky's opinion (http://www.joelonsoftware.com/items/2003/10/13.html) (he's co-founder of Stack Overflow).

Mirage
24-03-2012, 10:19 AM
Of modern language features only generics are really useful.
As it is really boring to copy/paste the same code just to create a hash map with different key/value types.
From the other side, in Delphi generics are achievable without language support - there is an include-based approach compatible with older versions of Delphi and FreePascal.
So I wrote a library with generic collections and algorithms based on the approach and have no need in a language support of generics.

code_glitch
24-03-2012, 01:53 PM
Sorry for the potentially ignorant question, but how much of that is/will be supported by FPC?

Eric
24-03-2012, 02:26 PM
Generics are very useful for containers, they help maintain strong typing and reduce the number of casts. Outside of that, they can get a bit obtuse (IME). The built-in Delphi generics are quite inefficient though, so those are probably not a good idea in game code (not to mention the compiler isn't very good with them, and you can end up with weird internal compiler errors or huge executables).
For simple containers, they compete with arrays (dynamic or not), which typically have less overhead, and can be just as strongly-typed. So for games, I would say they're good outside performance-critical code, and the with caution.

Duck-typing I'm not a fan of, it's just too easy to let a dragon that can quack & walk into the pond (with devastating outcome).
Also many terms (in human language) are just too ambiguous, a good deal of programming is about removing the ambiguity to express what needs to be done clearly.

Await and asynchronicity are both useful and impractical for games, useful because it means you can use multi-core more easily, and impractical because unless you're on a console, you can't assume a certain number of cores are at your disposal, nor how much time it'll take to do something. So they can only be used for stuff peripheral to the game (like pre-loading textures, reducing wait between levels, etc.), but can't be used for anything time or frame-critical (unless you bump the requirements to things like "quad-core CPU required and I mean a real quad-core not just a dual-core with hyperthreading")

Nested classes, well the only practical use seems to be for enumerators, apart that, they just get too verbose and too specific.

for..in loops, they save some typing and improve clarity, I use them whenever I can :)

final methods & sealed classes: I use them mostly to guarantee a class isn't subclassed, which means you can do "if obj.ClassType=TSealedClass" rather than having to use "in". It's a micro-optimizations though, and may not be relevant in general, but it can have its uses.

anonymous methods: can be quite useful and reasonably efficient, though in the case of Delphi, be wary of compiler internal errors.

Jimmy Valavanis
24-03-2012, 04:53 PM
Hmmm, most of these new features seems complete new to me.
Generics must be the C++ equivelant for function templates, right? You can save some typing, but nothing more. Really, besides the max and min functions where else can I use it? I'd prefer to rewrite some code.
Oxygene's await keyword and nested classes...., well, I don't know what are these, really!
For..in loops. Come on, this is javascript, not pascal! Besides I'm trying not to use for loops at all, instead I like writing while loops using for the exit-loop-contition some pointer checking (perhaps a bit faster code).
final methods: Unfortunatelly I don't know what's this. :(

Even when I'm using forms, not only in games, I'm trying to stay 'procedural", without using objects/classes. Also as an old school programmer I 'm not used to some newer features. The only, let's say, year 2000 era feature I'm using are the optional parameters with default values.

pitfiend
26-03-2012, 02:24 AM
I never used any new feature since delphi 7. Some time ago I migrated some customer applications to delphi 2007, just to improve UI with that fancy glass stuff on windows 7. I stay away from generics, anonymous and unicode, we don't need that. For loops, I like while/repeat ones 'cause they are flexible, you define elegantly when they must exit and didn't breaks readability as the break clause in for loops, it's ugly as using goto... yuck!

SilverWarior
26-03-2012, 05:45 AM
Even when I'm using forms, not only in games, I'm trying to stay 'procedural", without using objects/classes. Also as an old school programmer I 'm not used to some newer features. The only, let's say, year 2000 era feature I'm using are the optional parameters with default values.

Do you know that each form, control, component is objec/class? So while you think that you don't work with objects/classes you are. The only difference is that you only use existing predefined classes and don't define new ones by yourself.
But object/classes are whats making object orineted programing language to what they are. When used properly they can be verry powerful.
For instance. Lets say that you have your own class defining some ingame character. This class can contain various properties and even methods.
Properties act similar to variables but the main difference is that you can assign special so caled getter/setter methods to each property. In setter method you can for instance validate that new value of this property is valid before you change it to a new value. In getter mehod you can even calculate the result from several different variables. The best thing is that all this is being done automaticly.
Methods can be used for executing some special parts of code wich is related to this class.

For more info on classes I recomend reading:
http://delphi.about.com/od/oopindelphi/a/delphi_oop4.htm
http://delphi.about.com/od/oopindelphi/a/delphi_oop6.htm

Or even better go trough all Object oriented tutorials staring with
http://delphi.about.com/od/oopindelphi/a/delphi_oop1.htm

Jimmy Valavanis
26-03-2012, 01:30 PM
Do you know that each form, control, component is objec/class? So while you think that you don't work with objects/classes you are. The only difference is that you only use existing predefined classes and don't define new ones by yourself.

Obviously, if someone uses forms and components is working with classes. But I prefer to write the core/functionality of each program without using oo and just use the VCL for the user interface. It's, let's say, my personal way of programming. In most cases when I'm using classes is when I have to make a component, in fact I'm still using components I've made a long-long time ago, some of them are still in my old page (http://www.geocities.ws/jimmyvalavanis/programming/delphi/index.html). But as I said, I prefer "procedural" programming.


But object/classes are whats making object orineted programing language to what they are. When used properly they can be verry powerful.

Sure, but on the other hand there is nothing you can do using classes that can not be done procedurally. I'm talking on problem solving / solution aspect.


For instance. Lets say that you have your own class defining some ingame character. This class can contain various properties and even methods.
Properties act similar to variables but the main difference is that you can assign special so caled getter/setter methods to each property. In setter method you can for instance validate that new value of this property is valid before you change it to a new value. In getter mehod you can even calculate the result from several different variables. The best thing is that all this is being done automaticly.
Methods can be used for executing some special parts of code wich is related to this class.

Data validation can be done as well as without using classes. An, well, nothing is being done automaticaly, you still have to write the code for the class. Instead of writting a procedure that evaluates a result from different variables you write the "getter" function. Instead of writting a "setter" funcion for your class, you write a validation function before setting the data. It's the same thing.

Now imagine that you have a few hundred available fuctions to define the behaviour of you character. What will you do? Write a class with hundreds of member functions, all in the same unit, having a 1MB source code unit, or using functions and split the source code into more units? From my point of view the second solution seems easier to maintain.

LP
26-03-2012, 11:57 PM
To Jimmy Valavanis:
I would really recommend that you learn OOP and possibly get books and take some courses on this. A full software engineering course would be best, but it will take significant time, maybe years. You'll learn that many of the points that you are making here are not true and are mostly due to your lack of knowledge on the matter, which actually you have admitted yourself.

Long story short: no, procedural programming is neither more efficient, nor it is the best approach at software development, on any possible level. There is no single application that you'd want to develop using procedural approach, trust me on this. ;)

WILL
27-03-2012, 01:12 AM
OOP, though great if you understand it isn't necessary to make a game, but like Lifepower says, it isn't the "best way." You have to work with what you know, however learning new things is always handy. There is a flip-side to this though.

Code should aid the programmer in their creations, not take them over. My advice is to be cautious when adding code to your game projects that are in-progress that is new to you. It's great to learn new things, but to actually finish a project, you need to pace yourself and don't over-exceed your knowledge with research beyond what is needed to complete your current project should you actually wish to finish it. You'll find that this will keep you productive, while allowing you to still learn a few things for each project should you choose to keep pushing your programming knowledge.

I didn't really mean to get into older concepts like OOP, however since we already broached the topic, I do think it was one of the greatest things to happen to the original Pascal syntax. I, myself have a bit of a hybrid style of coding though. I love writing objects and fleshing them out with all the procedures and functions required, but I hate getting too complex with OOP. I find that you can spend hours and hours designing the "perfect" object class and at the end of your day you may have this great code that can do wondrous things, yet where is your actual game in all of this?

Jimmy Valavanis
27-03-2012, 07:14 AM
To Jimmy Valavanis:
I would really recommend that you learn OOP and possibly get books and take some courses on this. A full software engineering course would be best, but it will take significant time, maybe years. You'll learn that many of the points that you are making here are not true and are mostly due to your lack of knowledge on the matter, which actually you have admitted yourself.

I admit that I'm unfamiliar with the most new features mentioned here but I'm not unfamiliar with OOP, as my thesis back in early 90's was involving a lot of OOP programming using Borland Pascal 7.0.
I still keep in my bookshelf a couple of my old OOP books (not only pascal but also C++). And I've actually read them all :)


Long story short: no, procedural programming is neither more efficient, nor it is the best approach at software development, on any possible level. There is no single application that you'd want to develop using procedural approach, trust me on this. ;)

The point is that I don't really like OOP, maybe the majority avoids procedural approaches, but I do like programming this way. Of course I'll re-use a component, or a class to develop something fast, but when I want to write code (not when I want to make a programm to do something - when I want to make something to enjoy making it) I prefer the procedural way.


OOP, though great if you understand it isn't necessary to make a game, but like Lifepower says, it isn't the "best way." You have to work with what you know, however learning new things is always handy. There is a flip-side to this though.

Making games it's my hobby, not my profession. If I have to learn new programming techniques, or even new programming languages, for my job as a software engineer, sure I'll do my homework.


Code should aid the programmer in their creations, not take them over. My advice is to be cautious when adding code to your game projects that are in-progress that is new to you. It's great to learn new things, but to actually finish a project, you need to pace yourself and don't over-exceed your knowledge with research beyond what is needed to complete your current project should you actually wish to finish it. You'll find that this will keep you productive, while allowing you to still learn a few things for each project should you choose to keep pushing your programming knowledge.

Let's imagine a fisherman: He uses a sophisticated trawl with a GPS, a super-tech radar to track the fishes and he is fishing with nets to gather as many fishes as he can to make the living, but during weekend he prefers his little boat and a simple hook because he likes fishing this way. He'll gather less fish, or he 'll need more time to gather many fishes, but he'll enjoy it!


I didn't really mean to get into older concepts like OOP, however since we already broached the topic, I do think it was one of the greatest things to happen to the original Pascal syntax. I, myself have a bit of a hybrid style of coding though. I love writing objects and fleshing them out with all the procedures and functions required, but I hate getting too complex with OOP. I find that you can spend hours and hours designing the "perfect" object class and at the end of your day you may have this great code that can do wondrous things, yet where is your actual game in all of this?

Well, I just love writing procedures instead of involving objects, especially with multi-level hierarchy. In addition, when I'm developing something for myself as a hobbyist I tent to be as low level as I can. Maybe sometimes I'm reinventing the wheel, but that's the way I like it ! :) :) I like my "USES" section to include only my code :) :)

Ñuño Martínez
27-03-2012, 10:40 AM
The way I work is "procedural using objects". That is, the main program flow is procedural but I use objects where I think they should be.

For example, in games I do all game logic by procedures and functions but I create classes to manage maps/worlds, and also for characters (player, enemies, NPCs ...). So I don't use pure procedural nor pure OOP.

LP
27-03-2012, 01:24 PM
Code should aid the programmer in their creations, not take them over. My advice is to be cautious when adding code to your game projects that are in-progress that is new to you. It's great to learn new things, but to actually finish a project, you need to pace yourself and don't over-exceed your knowledge with research beyond what is needed to complete your current project should you actually wish to finish it.
I agree, there is YAGNI (http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It) principle that describes exactly that.



Let's imagine a fisherman: He uses a sophisticated trawl with a GPS, a super-tech radar to track the fishes and he is fishing with nets to gather as many fishes as he can to make the living, but during weekend he prefers his little boat and a simple hook because he likes fishing this way. He'll gather less fish, or he 'll need more time to gather many fishes, but he'll enjoy it!
In this case, OOP is the little boat and a simple hook, which later you can upgrade to GPS and super-tech radar. But, you are trying to fish with a fork swimming in an inflatable toy. Sure, it can be a fun sport, but you won't get much fish, if any. ;)

P.S. Jimmy, please try not to get offended, there is no need to multi-quote everything and argue about what you don't know or don't fully understand (remember unskilled and unaware (http://www.damninteresting.com/unskilled-and-unaware-of-it/) article). My suggestion to you was to try and learn new things, which could be fun and you might even get surprised.

The fact is, you can use OOP for the smallest applications and create elegant code, that later you can extend, modify and even reuse. If you "think procedural" and use OOP mostly as a data type (e.g. objects for data) or only because you have to, this approach is called anti-pattern (http://en.wikipedia.org/wiki/Anti-pattern). If you want to keep closed-minded about it, nobody is forcing you to try new/better ways, just keep using what you know. :)

Jimmy Valavanis
27-03-2012, 07:52 PM
It's really difficult not to get offended when someone deliberately offends you :(

Carver413
27-03-2012, 08:25 PM
Its time's like this when you wish there was an ignore button. don't let it get you down Jimmy some people just don't know when to quit.

WILL
27-03-2012, 08:28 PM
I don't think that Lifepower meant to be offensive. I've seen him being offensive, this really isn't what I'd categorize it as. :) (Sorry Yuriy, it's sort of a defense though. ;)) He just has some strong opinions about code, which is fine, it's primarily a coders forum after all. OOP has it's benefits, yet learning new things does sometimes get in the way of progressing with active projects. Even news ones so I can see why you aren't crazy about the idea of taking up something new. There is validity there.

If you find you are able to do what you need with your own coding knowledge then stick with it until you feel you want to dig deeper into the rabbit hole. Should you want to learn a more advanced coding style, there is benefit in learning OOP. So when or if you become ready for such, Lifepower's suggestions would help you in that way. I think this is where he was going with it, not meaning to tear your skills apart and tell you you are doing it wrong. Just explain to you that it is an older way and there are much newer ones that have been developed since.

LP
27-03-2012, 10:52 PM
It's really difficult not to get offended when someone deliberately offends you :(
Can you please send me a PM mentioning what parts of my post did you find offensive? I'm sorry but it was not my intention. I can erase my post, if you wish. In most cases I'm just trying to be direct and straight to the point. My intention was to help/recommend. However, it was not me who was flashing thesis works and books; I think you should put away the pride and chill. ;)

WILL
28-03-2012, 04:09 AM
As much as I like a good case scenario to try for problem solving, this is getting a tad off topic. Why not start another thread about Object Oriented Programming vs. Procedural Programming? :)

UPDATED: Ok I pulled the trigger on it. Sorry, but I had to move it to a new thread. New area of discussion, new thread that's how we roll at PGD. Sometimes small deviations are ok, but not huge full throttle shifts in topic completely. Yours was a doozy.

However here is the link to the new thread (http://www.pascalgamedevelopment.com/showthread.php?13187-Proceural-Programming-vs-Object-Oriented-Programming). We do believe in convenience. All are welcome to beat each other to a pulp there. :) ...just do it nice and politely or I'll send the evil Google preview after you.

WILL
28-03-2012, 09:07 PM
Getting this thread back on topic however, I am interested to see what kind of new language features that Oxygene will bring as it continues to evolve into it's very distinct language.

Is there a feature you would like to see added to any of the existing Pascal-based languages or dialects?

Eric
29-03-2012, 07:32 AM
At the risk of starting another flame war, I would say some form of templates could be very useful. C++-like templates.

Generics are all fine and dandy when it comes to containers, but beyond those, they quickly become quite messy & unwieldy. Also they favor bloat-ware/code complexity on the generated binary, which isn't very desirable for games.

For games, the downsides of templates (weird, hard to understand compile-time errors) would matter much less than their benefits.

For those that don't know the difference, it can be summarized by saying that a generic can be syntax-checked on its own (outside of any specialization), while a template is closer to a macro, that is syntax-checked on specialization.

For instance, suppose you want to add two "things", with templates, you can write just:


function Add<T>(a, b : T) : T;
begin
Result := a + b
end;

It'll work for Integer, String, Double, or anything for which you overloaded the + operator (like vector records/static arrays).
And you'll get an error for things that don't support the + operator, like Add<Boolean>.

But it won't work for generics, as a generic type T can't always be added... so you'll get a compile-time error on the generic.
To make it work, you have to add an interface and a constraint:


type IAddable<T> = interface
function Add(b : T) : T;
end;

function Add<T : IAddable<T>>(a, b : T) : T;
begin
Result := a.Add( b );
end;

but then it'll only work for generic classes that implement the generic IAddable interface, it won't work for simple types, records or arrays unless you box them.

It also makes a simple generic sorter a creation of hideous complexity, as you'll need a generic IComparer<T> (cf. the RTL source...), while writing a template-based sorter can be trivial. Same goes for most algorithms. Soon enough, you find yourself piling up generic interfaces.

Now, all isn't rosy with templates, as templates can use other templates, so it's possible to get at the specialization errors that relate to a sub-sub-sub-template of the template you're using, with an error message that can be eminently cryptic because it bears only very indirect relation to what you were trying to do.

LP
29-03-2012, 12:58 PM
At the risk of starting another flame war, I would say some form of templates could be very useful. C++-like templates.

Generics are all fine and dandy when it comes to containers, but beyond those, they quickly become quite messy & unwieldy. Also they favor bloat-ware/code complexity on the generated binary, which isn't very desirable for games.
I think the Duck Typing concept that Jason mentioned at the beginning is similar to the templates that you are describing. Even though you sacrifice maintainability and readability for a more compact code, I think they could be much more useful than generics. Also, you can do some weird things with C++-like templates. ;)

Eric
29-03-2012, 01:08 PM
I think the Duck Typing concept that Jason mentioned at the beginning is similar to the templates that you are describing.

Not really, duck-typing is a form of implicit interfaces (and that's how Oxygene implements them under the hood btw), the C++ templates are more of a form of restricted macros, which can recursively reference each other.

Another aspect is that templates are (as far as C++ goes) fully resolved at compile-time, while duck-typing can often be resolved only at run-time. So duck-typing is usually tied to dynamic typing, and for strongly typed languages, it involves some form of RTTI.

Mirage
29-03-2012, 06:33 PM
At the risk of starting another flame war, I would say some form of templates could be very useful. C++-like templates.
...
It also makes a simple generic sorter a creation of hideous complexity, as you'll need a generic IComparer<T> (cf. the RTL source...), while writing a template-based sorter can be trivial. Same goes for most algorithms. Soon enough, you find yourself piling up generic interfaces.

Now, all isn't rosy with templates, as templates can use other templates, so it's possible to get at the specialization errors that relate to a sub-sub-sub-template of the template you're using, with an error message that can be eminently cryptic because it bears only very indirect relation to what you were trying to do.

I wrote here about an include-based technique which can be used to create generic containers and algorithms.
For algorithms it works fine and is simple to use:


procedure Sort(Count: Integer; Data: array of TSortData);
type
_SortDataType = TSortData;
const
// Algorithm compile-time options
_SortOptions = [soDescending];

// Optional comparator function needed if TSortData cannot be compared directly with "<" operator
function _SortCompare(const V1,V2: TSortData): Integer; inline;
begin
Result := V1.Value - V2.Value;
end;

{$I gen_algo_sort.inc} // include type-independent sort implementation

end;

I forgot to mention another useful feature of recent Delphi versions - full-blown RTTI.
It can be used for many things, including dynamic code update, when you can compile new version of, for example, character AI class and dynamically update it in application/editor to immediately test the new behaviour without even restarting a level.

Eric
30-03-2012, 03:16 AM
I forgot to mention another useful feature of recent Delphi versions - full-blown RTTI.
It can be used for many things, including dynamic code update, when you can compile new version of, for example, character AI class and dynamically update it in application/editor to immediately test the new behaviour without even restarting a level.
You can, but that part is quite fragile when done through RTTI, not because of RTTI, but because of memory management and the RTL/VCL isn't safe, so it's very easy to end up with dangling pointers, memory leaks and memory overwrites. You need some severe sandboxing and safety to be able to edit & run things interactively, and RTTI doesn't provide that.