www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Module-based programming

reply "Land" <Land gmail.com> writes:
I'm confused when it comes to modules.

I've read somewhere that modules are basically 'singleton
classes' and that anything that doesn't need its own state should
not needlessly be put inside a class.

But what if I want to create a simple OpenGL shader object. Do I
create a class like this:

class Shader
{
      // Method
      // Method
      // Method
      // Method

      // Field
      // Field
      // Field
}

Or do I have a structure that I operate on via module methods?
(C-style, basically)

struct Shader
{
      // Field
      // Field
      // Field
}

// Method
// Method
// Method
// Method

It's probably clear to you guys, but I'm stumped.

Thanks for any answers
Jul 26 2013
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-07-26 11:12, Land wrote:
 I'm confused when it comes to modules.

 I've read somewhere that modules are basically 'singleton
 classes' and that anything that doesn't need its own state should
 not needlessly be put inside a class.
Modules are not singleton classes. They haven't much to do with classes at all. I mean, you cannot inherit modules.
 But what if I want to create a simple OpenGL shader object. Do I
 create a class like this:

 class Shader
 {
       // Method
       // Method
       // Method
       // Method

       // Field
       // Field
       // Field
 }

 Or do I have a structure that I operate on via module methods?
 (C-style, basically)

 struct Shader
 {
       // Field
       // Field
       // Field
 }

 // Method
 // Method
 // Method
 // Method

 It's probably clear to you guys, but I'm stumped.

 Thanks for any answers
In general I would say go with a class, but since you mentioned OpenGL it probably needs to go very fast and minimize allocations. In that case a struct would probably be better, if you're going to use a lot of these Shaders. It also depends on if you need value semantics or reference semantics for Shader. Classes always have reference semantics, structs have value semantics by default, and if you use a pointers you'll get reference semantics. Note that you can have methods in a struct too. So in any case, I would say, don't put the functions at module scope. -- /Jacob Carlborg
Jul 26 2013
prev sibling next sibling parent reply "JS" <js.mdnq gmail.com> writes:
On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote:
 I'm confused when it comes to modules.

 I've read somewhere that modules are basically 'singleton
 classes' and that anything that doesn't need its own state 
 should
 not needlessly be put inside a class.

 But what if I want to create a simple OpenGL shader object. Do I
 create a class like this:

 class Shader
 {
      // Method
      // Method
      // Method
      // Method

      // Field
      // Field
      // Field
 }

 Or do I have a structure that I operate on via module methods?
 (C-style, basically)

 struct Shader
 {
      // Field
      // Field
      // Field
 }

 // Method
 // Method
 // Method
 // Method

 It's probably clear to you guys, but I'm stumped.

 Thanks for any answers
Non-member methods require you to pass the object you want to modify... do you really want to do all that extra typing? It's your choice... you wanna program in C or C++?
Jul 26 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 26 July 2013 at 11:42:25 UTC, JS wrote:
 On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote:
 I'm confused when it comes to modules.

 I've read somewhere that modules are basically 'singleton
 classes' and that anything that doesn't need its own state 
 should
 not needlessly be put inside a class.

 But what if I want to create a simple OpenGL shader object. Do 
 I
 create a class like this:

 class Shader
 {
     // Method
     // Method
     // Method
     // Method

     // Field
     // Field
     // Field
 }

 Or do I have a structure that I operate on via module methods?
 (C-style, basically)

 struct Shader
 {
     // Field
     // Field
     // Field
 }

 // Method
 // Method
 // Method
 // Method

 It's probably clear to you guys, but I'm stumped.

 Thanks for any answers
Non-member methods require you to pass the object you want to modify... do you really want to do all that extra typing? It's your choice... you wanna program in C or C++?
Is it really extra typing? Depending on how you format your code, you might just be swapping a '.' for a ',' Also, we have UFCS (universal function call syntax): "foo(x, y, z)" can be written as "x.foo(y, z)"
Jul 26 2013
parent reply "JS" <js.mdnq gmail.com> writes:
On Friday, 26 July 2013 at 11:58:13 UTC, John Colvin wrote:
 On Friday, 26 July 2013 at 11:42:25 UTC, JS wrote:
 On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote:
 I'm confused when it comes to modules.

 I've read somewhere that modules are basically 'singleton
 classes' and that anything that doesn't need its own state 
 should
 not needlessly be put inside a class.

 But what if I want to create a simple OpenGL shader object. 
 Do I
 create a class like this:

 class Shader
 {
    // Method
    // Method
    // Method
    // Method

    // Field
    // Field
    // Field
 }

 Or do I have a structure that I operate on via module methods?
 (C-style, basically)

 struct Shader
 {
    // Field
    // Field
    // Field
 }

 // Method
 // Method
 // Method
 // Method

 It's probably clear to you guys, but I'm stumped.

 Thanks for any answers
Non-member methods require you to pass the object you want to modify... do you really want to do all that extra typing? It's your choice... you wanna program in C or C++?
Is it really extra typing? Depending on how you format your code, you might just be swapping a '.' for a ',' Also, we have UFCS (universal function call syntax): "foo(x, y, z)" can be written as "x.foo(y, z)"
But what about protection semantics? Access to this? Properties? Virtual functions?
Jul 26 2013
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 26 July 2013 at 13:11:33 UTC, JS wrote:
 On Friday, 26 July 2013 at 11:58:13 UTC, John Colvin wrote:
 On Friday, 26 July 2013 at 11:42:25 UTC, JS wrote:
 On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote:
 I'm confused when it comes to modules.

 I've read somewhere that modules are basically 'singleton
 classes' and that anything that doesn't need its own state 
 should
 not needlessly be put inside a class.

 But what if I want to create a simple OpenGL shader object. 
 Do I
 create a class like this:

 class Shader
 {
   // Method
   // Method
   // Method
   // Method

   // Field
   // Field
   // Field
 }

 Or do I have a structure that I operate on via module 
 methods?
 (C-style, basically)

 struct Shader
 {
   // Field
   // Field
   // Field
 }

 // Method
 // Method
 // Method
 // Method

 It's probably clear to you guys, but I'm stumped.

 Thanks for any answers
Non-member methods require you to pass the object you want to modify... do you really want to do all that extra typing? It's your choice... you wanna program in C or C++?
Is it really extra typing? Depending on how you format your code, you might just be swapping a '.' for a ',' Also, we have UFCS (universal function call syntax): "foo(x, y, z)" can be written as "x.foo(y, z)"
But what about protection semantics? Access to this? Properties? Virtual functions?
There are lots of good reasons to use methods instead of free functions, I'm just saying that having to explicitly pass the object to the function isn't a particularly big one, especially in D.
Jul 26 2013
prev sibling parent "Dicebot" <public dicebot.lv> writes:
On Friday, 26 July 2013 at 13:11:33 UTC, JS wrote:
 But what about protection semantics? Access to this? 
 Properties? Virtual functions?
Non-public methods should not be free functions. Same goes for virtual ones. Access to this is no different from access to first parameter of function. That still leaves tons of utility stuff people usually implement as methods despite the fact they don't really need to be ones.
Jul 26 2013
prev sibling next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote:
 struct Shader
 {
      // Field
      // Field
      // Field
 }

 // Method
 // Method
 // Method
 // Method
I personally favor this approach whenever possible, it fits nicely with UFCS and allows to keep data type signature clean from unrelated stuff. My guideline is "If something simply operates on an aggregate, make it a free function. If it requires some knowledge about private aggregate state and/or is something done by aggregate, make it a method".
Jul 26 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/26/2013 05:13 AM, Dicebot wrote:

 On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote:
 struct Shader
 {
      // Field
      // Field
      // Field
 }

 // Method
 // Method
 // Method
 // Method
I personally favor this approach whenever possible, it fits nicely with UFCS and allows to keep data type signature clean from unrelated stuff. My guideline is "If something simply operates on an aggregate, make it a free function. If it requires some knowledge about private aggregate state and/or is something done by aggregate, make it a method".
+1 I apply the same idea in C++ as well. Of course, the decision of whether it is a struct or class is based on other factors. (This is not an issue in C++ because structs and classes are semantically same there.) And yes, UFCS helps with this in D. I had come up with a quick example: Once a Car class provides basic functionality, functions like canTravel() should not be members: [1] class Car { enum economy = 12.5; // kilometers per liter (average) private double fuelAmount; // liters this(double fuelAmount) { this.fuelAmount = fuelAmount; } double fuel() const { return fuelAmount; } // ... } bool canTravel(Car car, double distance) { return (car.fuel() * car.economy) >= distance; } Ali [1] http://ddili.org/ders/d.en/ufcs.html
Jul 26 2013
parent reply "Land" <Land nospam.com> writes:
Thanks for all the replies. What about inheritance and 
interfaces, though? Am I supposed to put all the 
interface/inherited methods into the object and all the other, 
utility methods, as free functions? Do I understand that 
correctly?
Jul 26 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/26/2013 08:33 AM, Land wrote:

 What about inheritance and interfaces,
 though? Am I supposed to put all the interface/inherited methods into
 the object
At least technically, yes. There is no other way for interfaces and function overriding.
 and all the other, utility methods, as free functions?
Some people think that as long as a function can be implemented as a free-standing function, then it should be a free-standing function. My earlier canTravel() is a good example. (Aside: In D, there is no free-standing function, they are all at least parts of modules.) Others think that any function closely related to a type should be a member function. Interestingly, canTravel() is good example here as well. :) Since most modern cars do report estimated distance the car can go with the remaining fuel, canTravel() can also be designed to be a member function. Ali
Jul 26 2013
prev sibling parent "Rikki Cattermole" <alphaglosined gmail.com> writes:
On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote:
 I'm confused when it comes to modules.

 I've read somewhere that modules are basically 'singleton
 classes' and that anything that doesn't need its own state 
 should
 not needlessly be put inside a class.

 But what if I want to create a simple OpenGL shader object. Do I
 create a class like this:

 class Shader
 {
      // Method
      // Method
      // Method
      // Method

      // Field
      // Field
      // Field
 }

 Or do I have a structure that I operate on via module methods?
 (C-style, basically)

 struct Shader
 {
      // Field
      // Field
      // Field
 }

 // Method
 // Method
 // Method
 // Method

 It's probably clear to you guys, but I'm stumped.

 Thanks for any answers
Personally I have a few rules with deciding between a class and a struct. A struct contains either data or functions (for global grouping them) although I'm sure somebody will say performance wise that could be bad. A class contains both data and methods to manipulate it. With regards to free functions for classes I look at it this way. If it needs the internal state it should probably be a method. If not probably external. All required methods also should be on the class. These should be not creating new instances of said class as well. Oh and a nice syntax for those free functions is with. with(instance) { } So instead of typing instance.m, m will suffice.
Jul 26 2013