News:

SimuTranslator
Make Simutrans speak your language.

German in the code

Started by felo, March 10, 2010, 05:48:22 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ters

Ogre3D is not an example to follow in my opinion. I hated programming against it, always feeling unsecure of whether I needed to explicitly free/close/destroy something, or whether some manager did it for me. It would have worked a bit better in a managed language like C# or Java. I seem to recall some hidden singletons, which you had to construct with new, but which then lived on as a singleton. It's possible that I remember that from CEGUI, which was even worse.

prissi

If one really wants proper OOP (whatever this is, this seems to change a lot every ten years ... ) then properly one should rather reimplement Simutrans in Java: Full portability, Garbage collection, standadized GUI, graphics, network code, Android "native" ...

Maybe singletons will be considered the worst idea of OOP in ten years. (Just as a provocative teaser.)

The same argument about templates can be used about the GUI and almost any part of the program. But I am sure, after ten years any program will look old to anybody who comes with the current "state of the art" knowledge. When I started simutrans coding, it did not even compile on MSVC.

That said, we are slowly going towards a better readable code, or?

eipi

Quote from: kierongreen on September 19, 2013, 05:24:51 PM
To clarify my opinions on documentation - .h files should describe what a function does, .cc files should describe how a function works (if it's not obvious).

I like this - though this has the risk of duplicate comments in .h and .cc files. In my opinion in .h files should give a quick overwiew of the "capabilities" of the class, while documentation in .cc files can be done either directly in code, or at the start of the function if the algorithm needs an overall description.

As to translating and refactoring code - What about focusing on non-gui-related classes like ding_t and derived classes for the time being and wait until the gui theme patch is in place? For example ding_t::ist_entfernbar() can be refactored to ding_t::is_removable(); this does not interfere with the gui as far as I can see.

Markohs

#178
Quote from: Ters on September 19, 2013, 05:46:56 PM
Ogre3D is not an example to follow in my opinion. I hated programming against it, always feeling unsecure of whether I needed to explicitly free/close/destroy something, or whether some manager did it for me.

Well, I had a similar feeling at some times too. I think this can be mitigated on many ways, for example:

* if you get a object as a result of a manager call let's say (just an example) log_t logmanager_t::get_logger(...):
  + if you want to stop using it, you need to logmanager_t::destroy(log)
  + when the manager is destroyed, he'll automatically destroy al logs not destroyed already.
* you supply a object to a manager, you are responsable of deleting it afterwards, because the manager will copy it if it needs to.

Dunno, I'll see what I can figure, some rule of thumbs, because what I don't really want to do is use smart pointers nor garbage collection.

Quote from: Ters on September 19, 2013, 05:46:56 PM
It would have worked a bit better in a managed language like C# or Java.

Yep, as you know it's one of the problems derived from the absolute flexibility in C++, memory management is 100% manual.

Quote from: Ters on September 19, 2013, 05:46:56 PM
I seem to recall some hidden singletons, which you had to construct with new, but which then lived on as a singleton. It's possible that I remember that from CEGUI, which was even worse.

Yep, that should not happen. I'm exploring a root_t:: singleton where *all* managers are created in the correct order and destroyed accordingly in shutdown.

I'm also for example thinking if objects like umgebung_t need to be turned into singletons too, I like how umgebung_t works in current code, the problem is having to declare each static member in the .cc *also*, but the alternative is turning all:

if(umgebung_t::mute_midi)

into:

if(umgebung_t::get_singleton()->mute_midi)

So I think I'll maybe let that class stay as it is now.

Well, lots of things to experiment, if you want to have a look I can post the patch, but it's basically tests now, trash. :)

Dunno, let me do more experiments, maybe this all will end in the trash bin. :)

Quote from: prissi on September 19, 2013, 08:32:12 PM
If one really wants proper OOP (whatever this is, this seems to change a lot every ten years ... ) then properly one should rather reimplement Simutrans in Java: Full portability, Garbage collection, standadized GUI, graphics, network code, Android "native" ...

Yes, a modern language like java that makes objects mandatory and has garbage collection makes easier to program OO, but neither java nor C# give the performance C++ gives. From what I read all commercial games are written in C++, and use OO design, but ofc, and like kierongreen comments, performance critical parts have to remain a bit C-style.

Quote
Maybe singletons will be considered the worst idea of OOP in ten years. (Just as a provocative teaser.)

Hehehe, yep, maybe. The good thing about singletons, is, to start with, you can be 100% sure they are instanced just once, and having one singleton containing the rest of singletons you can control in which order they are created/deleted.

I'm following "Game engine Architecture" From Jason Gregory, Chapter 5.

tip: google "game engine architecture" , at least on my computer the fourth entry it's a pdf with that book, legal or not. But I have the book in paper, for the case the big boss is watching.

Quote
That said, we are slowly going towards a better readable code, or?

I think so, specially this last year, as a team effort, everybody it's making code cleaner. I'm happy about it. Specially Dwachs imho, that writes very clean code.

Markohs

Quote from: kierongreen on September 19, 2013, 05:24:51 PM
To clarify my opinions on documentation - .h files should describe what a function does, .cc files should describe how a function works (if it's not obvious).

I think this is very reasonable. I agree.

Quote from: eipi on September 19, 2013, 08:59:37 PM
As to translating and refactoring code - What about focusing on non-gui-related classes like ding_t and derived classes for the time being and wait until the gui theme patch is in place? For example ding_t::ist_entfernbar() can be refactored to ding_t::is_removable(); this does not interfere with the gui as far as I can see.

I'd say go ahead. But, are you planning to just rename methods/variables? Or are you renaming the classes and files (with the Makefile and VS project) too?

Ters

Quote from: prissi on September 19, 2013, 08:32:12 PM
Maybe singletons will be considered the worst idea of OOP in ten years. (Just as a provocative teaser.)

I've seen this already happen. The argument is that singleton is just a gloified global variable, and global variables are bad (according to purists).

Quote from: Markohs on September 19, 2013, 10:54:53 PM
you supply a object to a manager, you are responsable of deleting it afterwards, because the manager will copy it if it needs to.

The problem is that, especially with the kind of data structures Ogre3D operates on, copying might be forbiddingly expensive. There are also issues with instance sharing, so should the copy be deep or shallow. I feel that Ogre3D has chosen a strategy that they for practical reasons can't really follow (or so they believe at least), so they end up with the worst of both worlds.

Miziiik

#181
I already thought about reimplementing Simutrans in Java because good portability (mainly for Android). It should be easier to port Simutrans to Android with Java. If someone would use OOP it's easier to do it in Java than in C++. Java isn't  memory-intensive when code is clear. I think that Simutrans should't be memory-intensive in Java if the code will be clear.
http://msim.8u.cz/ Můj web o hře Simutrans - Moje addons, návody, odkazy, apod.

Markohs

Seeing java performance you'll have quite of a problem keeping it running smooth in that platform, I think. But it depends on map size and density of graphics on screen mainly, we need to figure how to make the game consume less CPU, I think.

Miziiik

Umm you're right. With big map and a lot of graphics on the screen it will maybe be more memory-intensive and use a lot of CPU. But with C++ it's harder to port to ARM. We can use other languages but it's a lot of work to reimplement Simutrans to that language.

A question to C++ programmers: Is OOP in C++ faster/better for Simutrans or not? About C# you're right with performance too. I learned C# and now I'm not using it. Now I think about "learning" java or C++ or other language but don't know what should I choose...
http://msim.8u.cz/ Můj web o hře Simutrans - Moje addons, návody, odkazy, apod.

Markohs

I don't really know why you and some others say porting C++ to ARM is harder, ARM is just a processor, and there is a ARM version of GCC. Where is the problem? :)

If we bring more OOP to simutrans, it will be to rearange code into more understadable units, simpler to understand and interchangeable/portable, nothing more.

Ters

Quote from: Markohs on September 20, 2013, 11:52:10 AM
If we bring more OOP to simutrans, it will be to rearange code into more understadable units, simpler to understand and interchangeable/portable, nothing more.

I find Simutrans quite neatly divided into units, except perhaps a few bits around the world, but I've read on this forum that some of that has changed since last I looked at it. The few things that aren't in classes actually ease porting in my opinion, since one can just replace a few functions rather than have to have interfaces and factory methods, or some hacks that are far worse.

Markohs

Well, you can allways create one static object with static functions/members for each .cc that doesn't use objects.

simmain_t, simevent_t, simsys_t, simgraph_t... I think that list can be pretty huge. But it's possible. The scripting part with squirrel can be a problem too, maybe.

Ters

It's possible, but it's fake OOP in my opinion. Kind of like in the South Park movie where the kids were told to say poo instead of ****. Nothing has changed, the code is still effectively organized the same way, there has just been added some OOP-ish keywords around it. And you have to write simgraph_t::draw_line rather than display_draw_line. (Or perhaps add a using. I don't remember if that works with anything but namespaces in C++. I always felt that using using defeated the point of namespaces.)

prissi

About ARM: First simutrans code works Bigendian as well as little endian. (For the PowerMac version be had done this). On Android, as far as I know, the y use the (stupid) Intels byte-twist endianess, so it shoudl work too. The onlz thing different on ARM is that words must be alinged.

Anyway, simutrans has been compiled for Android, so it works.

So concepts like multiple inheritance used in simutrans (mainly the sync_step and the GUI callbacks) would not work in JAVA. I am also not sure how efficiently store objects on tiles with a garbage collector.

Ters

Quote from: prissi on September 20, 2013, 04:53:08 PM
So concepts like multiple inheritance used in simutrans (mainly the sync_step and the GUI callbacks) would not work in JAVA. I am also not sure how efficiently store objects on tiles with a garbage collector.

I miss multiple inheritance in Java sometimes. They've sort of snuck it in in Java 8, though.

The garbage collector has nothing to do with efficient storage as far as I know. For storage, you can just envisage always having to use new for everything but primitives (char, int, boolean, etc.). There are some crazy alternate ways of allocating memory in Java, but I'm not sure it works for anything but primitive arrays (I've usually heard of just arrays of bytes).

eipi

Quote from: Markohs on September 19, 2013, 10:55:57 PM
I'd say go ahead. But, are you planning to just rename methods/variables? Or are you renaming the classes and files (with the Makefile and VS project) too?

Well, if I'm already translating it would make sense to also rename class names along the way. But we rather should do this in small steps. My next goal is to rename ding_t and methods, post a patch with these changes here and then work my way down to all classes derived from ding_t.
(I guess ding_t should be renamed to thing_t.)

What do you think about it?

kierongreen

I'd say obj_t to replace ding_t. Currently we have wayobj_t, groundobj_t and movingobj_t all being ding_t so making obj_t the generic class would seem to make some sense to me.

Although the argument against this is that there is a tabfileobj_t (used with tabfile_t).

Also thing_t (while I appreciate it is a literal translation of ding_t) sounds rather generic and... weak?

prissi

Kireons idea is great, as the description (besch) is called obj_besch_t ...

kierongreen

Bringing up the questions of what besch should be. Description is too long, ideas:
desc(ription)
def(inition) - directory would be defs?
type
class
header
?

Also, bauer to builder?

prissi

bauer is rather a manager, sicne it maintains the static lists and tools.

bsch -> desc (unique and short)

sdog

This thread suddenly became very interesting. Just learned a lot of new concepts by looking up what you're discussing in wikipedia. Thanks for that.

One OT question though: I don't understand why global variables are bad could someone tell why. Not a rethorical question, i believe you they are. It would be nice to know why.

I tend to use them from time to time in perl. (I wish there were some in f77 using something like main:parameter would be much nicer then includes of files with definitions or common blocks.)

Markohs

I understand obj_t makes complete sense reading your comments, and it does.

Anyway I'd like to suggest:

base_domain_obj_t
base_obj_t

because obj_t doesn't give enough information about that's the class about, the other names give a hint it's part from the "runtime object model", and base because it's the root of hierarchy. root_obj_t is a good name too.

I whoudn't say no to obj_t , but I feel like it's too short, and lacks context, meaning. :)

Quote from: sdog on September 21, 2013, 03:19:08 AM
This thread suddenly became very interesting. Just learned a lot of new concepts by looking up what you're discussing in wikipedia. Thanks for that.

Good, I feel a little bad because we are on offtopic, but I don't really know if splitting the topic is worth it. :)

Quote from: sdog on September 21, 2013, 03:19:08 AM
One OT question though: I don't understand why global variables are bad could someone tell why. Not a rethorical question, i believe you they are. It would be nice to know why.

The problem they have is since they are readable/writable by virtually any part of the code, you have  absolutely no idea who's modifying them in runtime, you have no way of controlling acces to it.

At a pratical level, if it's a global function (simutrans has a lot of that), you can allways debug and see on the stack from where in the code that routine was called from, but you can't do that on a variable. It's just calling for trouble, because if a bug related to that variable arises, you have absolutely no way to debug that, just looking at the code.

Why are they used? Because it's very easy to reach that vaiable, it's way easier than modifying a member variable of a class, ( a public class static member attribute is in that sense also a global variable, and a variable inside a namespace too), and performance-wise it's the fastest way to access a variable.

When you program, it's better to restrict your code to access variables inside a restricted namespace, ideally code should only modify variables on its own class, or declared inside te function (or parameters), the smallest the scope of variables your code touches, the less you have to take into account when designing and modifying your code.

Think of a donkey, those things they had on the eyes to see only what they had in front of them, to not get distracted by the envirnment. It's a metaphor, but you as a programmer, should read code as if you were wearing that.



if you are a disciplined programmer you know the function you have in front of your eyes only modifies variables you have in front of your eyes. If it accesses global variables, it could be interacting with code far away from what you are looking to, virtually anyewre, any .cc file could be accessing that variable too.

But global variables have their use, I use them sometimes, mainly when scripting, like you, in perl, or bash. But my oppinion is you should never ever use a global variable in C, under any circumstances, there is allways a better way to do it, even if it's at the cost of a few CPU cyles or memory accesses. It's a question of time you'll get a bug there. Modern languages like Java for example, don't even have a "global variable" concept, you have to fake it with singletons.

More wiki links, interesting related to this:

http://en.wikipedia.org/wiki/Scope_%28computer_science%29
http://en.wikipedia.org/wiki/Namespace

Sorry for the long post, I hope I didn't bore you. ;)

eipi

Quote from: Markohs on September 21, 2013, 03:56:59 AM
I understand obj_t makes complete sense reading your comments, and it does.

Anyway I'd like to suggest:

base_domain_obj_t
base_obj_t

What about simobj_t?  Otherwise obj_t seems OK for me too.
besch -> desc is a good idea.

Ideas for classes derived from ding_t:
(async)_wolke_t -> (async)_cloud_t
baum_t -> tree_t
ding_no_info_t -> (sim)obj_no_info_t
dummy_ding_t -> dummy_(sim)obj_t (or deprecated_(sim)obj_t or maybe a translation which points out this ding is ignored?)
gebaeude_t -> building_t
leitung_t -> powerline_t
raucher_t -> (I don't really know. smoker_t sounds bad :D)
vehikel_basis_t -> base_vehicle_t?
verkehrsteilnehmer_t -> traffic_t

prissi

verkehrteilnehmer includes pedestrians. As it is not used that frequently, maybe independent_vehicles and vehikel then to convoi_vehicle_t?

base_obj_t is for me not more informative that obj. Since this is used all over at countless places, why not call it obj?t. If we go from german to english, we should take advantage of the shorter words in this language compared to german.

Ters

Quote from: Markohs on September 21, 2013, 03:56:59 AM
The problem they have is since they are readable/writable by virtually any part of the code, you have  absolutely no idea who's modifying them in runtime, you have no way of controlling acces to it.

At a pratical level, if it's a global function (simutrans has a lot of that), you can allways debug and see on the stack from where in the code that routine was called from, but you can't do that on a variable. It's just calling for trouble, because if a bug related to that variable arises, you have absolutely no way to debug that, just looking at the code.

Why are they used? Because it's very easy to reach that vaiable, it's way easier than modifying a member variable of a class, ( a public class static member attribute is in that sense also a global variable, and a variable inside a namespace too), and performance-wise it's the fastest way to access a variable.

When you program, it's better to restrict your code to access variables inside a restricted namespace, ideally code should only modify variables on its own class, or declared inside te function (or parameters), the smallest the scope of variables your code touches, the less you have to take into account when designing and modifying your code.

Think of a donkey, those things they had on the eyes to see only what they had in front of them, to not get distracted by the envirnment. It's a metaphor, but you as a programmer, should read code as if you were wearing that.



if you are a disciplined programmer you know the function you have in front of your eyes only modifies variables you have in front of your eyes. If it accesses global variables, it could be interacting with code far away from what you are looking to, virtually anyewre, any .cc file could be accessing that variable too.

But global variables have their use, I use them sometimes, mainly when scripting, like you, in perl, or bash. But my oppinion is you should never ever use a global variable in C, under any circumstances, there is allways a better way to do it, even if it's at the cost of a few CPU cyles or memory accesses. It's a question of time you'll get a bug there. Modern languages like Java for example, don't even have a "global variable" concept, you have to fake it with singletons.

You touch on, but as far as I could see don't explicitly refer to the concept of no side effects. For readability, debugability and maintainability, a function should (ideally) only read its parameters and only write its return value. For objects in OOP, I assume (I don't think I've ever read it somewhere, but nothing else makes sense to me) methods (called member functions in C++) can modify the object's fields (member/instance variables).

Globals are also troublesome in terms of multithreading, especially when there are multiple CPUs or CPU cores with their own caches. Unless you explicitly synchronize the caches, which has a negative impact on performance, different threads may read different values from the same variable. This is in fact not restricted only to globals, but all mutable objects shared between the threads. The current best practice seems to be to never share mutable objects between threads, and non-constant globals are such a shared mutable object. Trying to follow this best practice may however lead to performance problems due to lots of copying of objects, depending on the application. For practical reasons, little to no production code adhere to textbook examples.

(This is almost like on the road, where everybody knows the speed limit (most of the time anyway), but almost always break it slightly. The few who do keep the speed limit stir up anger from some of the other drivers.)

kierongreen

QuoteIf we go from german to english, we should take advantage of the shorter words in this language compared to german.
Completely agree with this :)

Markohs

#201
Quote from: eipi on September 21, 2013, 08:05:32 AM
What about simobj_t?  Otherwise obj_t seems OK for me too.

I like simobj_t, perfect!

I also prefer shorter names, but I prefer to have a descriptive name than a cryptical one, making a class named obj_t is like having a variable named "var".


void f(char var)
{
   new obj_t obj;
   obj->set_var(var)


Lacks context, what are we doing?

It's not like you are gong to type the full name, you'll just select it from the dropbox once you are typing it on your IDE. I think you guys would completely hate programming java. :)

Ters

Quote from: Markohs on September 21, 2013, 12:03:49 PM
I like simobj_t, perfect!

I also prefer shorter names, but I prefer to have a descriptive name than a cryptical one, making a class named obj_t is like having a variable named "var".

I thought the same about obj_t. simobj_t seems to capture the fact that this base class is limited to simulated objects, or rather object simulated as distinct entities, since passengers are simulated, but not as a crowd, not as distinct entities.

Quote from: Markohs on September 21, 2013, 12:03:49 PM
It's not like you are gong to type the full name, you'll just select it from the dropbox once you are typing it on your IDE. I think you guys would completely hate programming java. :)

My Java IDE autocompletes wonderfully, my C++ IDE only occasionally and not as elegantly, often suggesting things that don't fit the context. At work, I actually deal with Java class names in excess of 60 characters, not including namespace (packages in Java terminology). If we don't keep the path into which we check out the source code short, some of these files can't be deleted by Windows (except through subst-ing) as the path is too long. (It's strange how creating the files is never a problem.) But as an amateur C++ developer, poor IDEs make me favor short names. I'd even like to drop _t, but I won't be demanding it.

kierongreen

simobj to me doesn't mean anything more than obj. When you consider we have simworld, simplayer, simhalt, sim* all over the game what does adding sim as a prefix actually mean?

About IDEs - some people don't use them. I don't for one.

Anyway, regarding context, examples of where ding is used at the moment are:

gr->obj_bei(0)->get_typ()==ding_t::baum

const ding_t *dt = gr->obj_bei(i);

ding_t::typ typ = (ding_t::typ)file->rd_obj_id();

case ding_t::old_automobil:
case ding_t::automobil: v = new automobil_t(welt, file, first, last);  break;
case ding_t::old_waggon:
case ding_t::waggon:    v = new waggon_t(welt, file, first, last);     break;
case ding_t::old_schiff:
case ding_t::schiff:    v = new schiff_t(welt, file, first, last);     break;
case ding_t::old_aircraft:
case ding_t::aircraft:    v = new aircraft_t(welt, file, first, last);     break;
case ding_t::old_monorailwaggon:
case ding_t::monorailwaggon:    v = new monorail_waggon_t(welt, file, first, last);     break;
case ding_t::maglevwaggon:         v = new maglev_waggon_t(welt, file, first, last);     break;
case ding_t::narrowgaugewaggon:    v = new narrowgauge_waggon_t(welt, file, first, last);     break;


In each case ding does not provide the context at the moment, other variable names or types around do. So obj would just be the same, only it's slightly shorter, and much shorter than some other suggestions which could really bulk out some sections of code making them less easy to read.

Markohs

I'm surprised you don't see any difference between obj_t and simobj_t. to me it's clear the first one is a generic object with no special traits and the second it's a object related to the simulation. obj_t it's the name you' d use when implementin let's say a list of generic objects.
Following tour reasoning we might use as well o_t or simply o.
You choose not using an IDE. I respect that,  but I don't think that means we need to change our guidelines to make it easier for people to write code like that. after all we are talking about a big project, not a complete toy project. We are being all reasonable too,  and proposing short enough alternate names..

Ters

Quote from: kierongreen on September 21, 2013, 03:29:33 PM
simobj to me doesn't mean anything more than obj. When you consider we have simworld, simplayer, simhalt, sim* all over the game what does adding sim as a prefix actually mean?

Those are names of files, not names of classes. And it's the files that has a meaningless prefix. Ideally, those files should be renamed to match the classes in them. I still get confused when looking for something, because the file has a sim prefix that I didn't think about.

sdog

Ok, i see, i would not have thought one would want to change a global variable.

Side effects of functions are something i deeply dislike. It is one of the main reasons i still don't understand the code i'm working with for 5+ years.

The globals i used before are all non-mutable. They are the parameters i give to a program. But it would be unwieldly to pass a dozen of integers and reals to a function.
(In Haskell i could easily do this by passing tuples [those are structs in C?])


Quoteif you are a disciplined programmer you know the function you have in front of your eyes only modifies variables you have in front of your eyes.
Can't you just set the function to 'pure'? Or are there no provisions for that in C?

fortrans way would be: PURE SUBROUTINE ...
... when this piece of obsolete junk has it, C++ like does as well?

QuoteSorry for the long post, I hope I didn't bore you.
No, not at all. Thank you Markohs very much for taking the time to explain this well and in detail. It is very clear now to me why global variables are to be avoided.


QuotePrissi: This is in fact not restricted only to globals, but all mutable objects shared between the threads.
Globals are exacerbating the problem already present. But this reminds me of something, it isn't enough a global mutable variable's state is never changed, the complier needs to know it also. Is there a way for the compiler to determine a variable is only changed at the start of a program when reading data. Or would it have to be declared as a constant (but then it would need to be known at compile time, not just at one point in runtime). (not a serious question i ask in hope of an answer, as such an answer would be highly language specific, and i wouldn't use C++ anyway)

Ters

Quote from: sdog on September 21, 2013, 06:32:30 PM
Ok, i see, i would not have thought one would want to change a global variable.

Side effects of functions are something i deeply dislike. It is one of the main reasons i still don't understand the code i'm working with for 5+ years.

The globals i used before are all non-mutable.

That would be a global constant, which I have never understood to be a problem.

Quote from: sdog on September 21, 2013, 06:32:30 PM
fortrans way would be: PURE SUBROUTINE ...
... when this piece of obsolete junk has it, C++ like does as well?

C++ inherits much of its rules from C, and C is ancient. The mindset of C is also very different from Fortran. Fortran has a higher level of abstraction. C on the other hand, is almost nothing more than glorified assembly, and lets you do anything (although screwing up the call stack requires climbing or falling into some implementation specific trap doors that aren't really part of the language).

Markohs

#208
Quote from: Ters on September 21, 2013, 06:49:38 PM
That would be a global constant, which I have never understood to be a problem.

Ofc they are not a problem, defining and using constants that you will use around the code it's good design.

What's nto desired is using literals inside the function, for example set_width(200),  if that code is to be constant, better define a constant like DESIRED_WIDTH=200 and put it on the top of the file,with the rest of constants, or try to centralize all the constants in a single file, or a reduced number of files. :)

I guess by pure function you refer to this:

http://en.wikipedia.org/wiki/Pure_function

It's not exactly the same concept, but it's similar. It's restrcting the scope of variables it can depend a bit less than a pure function, to just the parameters *AND* the class member variables. But nothing outside the class should affect it's behavior.

prissi

As such any function (which is not const) on an object can never be a pure function. Imho saying globals are bad, but then having object local variables in singletons is the same as using global. Only in a more complicated way.