02 Mar, 2009, JohnnyStarr wrote in the 1st comment:
Votes: 0
Ok, by now some of you want to strangle me, but please humor me on this.
I have asked similar questions on other posts, but i need some refinement
on a concept. In C# you can use "static classes" so that you can write global
functions while maintaining a Namespace structure right?

Ok, i'm learning ruby right now and have been exploring RocketMud which
follows the SocketMud approach. Because SM was written in C it makes sense that
it would have a more "procedural" approach. And I still dont know if it is a good practice to have either: Everything is a Class Object, or you have both, as in global static functions AND store all data in Objects (rooms, players, npcs, items etc)

RocketMud uses both and has a more "traditional" programming approach, not being to strict in OO. Infact it says "it has been modifed to a bit more OO"

The reason i ask is i am ready to move past all this theroetical debate and START PROGRAMMING! so any pointers would be nice.

:grinning:
02 Mar, 2009, David Haley wrote in the 2nd comment:
Votes: 0
What exactly is your question here? :wink:
02 Mar, 2009, Stormy wrote in the 3rd comment:
Votes: 0
If you want to see (IMO) a barebones MUD server written in the "Ruby way", check out TeensyMUD. RocketMUD is essentially a straight port of SocketMUD, with really only the most necessary portions using an OO approach. For someone coming into Ruby, RocketMUD is probably an easier tool to use, but I really wouldn't suggest using it as a guide for best practices.
02 Mar, 2009, JohnnyStarr wrote in the 4th comment:
Votes: 0
Thank you Stormy for a direct answer.

My exact questions would be:

QUESTION #1
Is it a good practice to combine
paradigms for a potentially massive application such as a mud server?
Although a strict OO approach yields benefits in encapsulation etc,
it also requires the developer to do some funky things to get it to work.
A mud server is basically an I/O app, so i don’t personally see why it would
have to be so strict in design.

QUESTION #2 (which is an example of question 1)

Is there a better way to do this?:

Rocket mud has a global function called "bug" so if something bombs, you can put in a (rescue) keyword to send a message to the bug.txt file:

#Ruby example
rescue
bug "Something is amiss!"
end

simple right? Now whether you are writing a class's member function or another global function all you have to do to reference the "bug" method
is simply type 'bug argument'.

In C# you can use 'public static' classes and it might look like this:

Bug.SendBug("Something is amiss")

Bug in this case is the name of the class. However, i'm not sure if you can do this in Ruby, and i dont see if that is desirable.

Now if you made "Bug" an instance object it might be like this:

b = Bug.new

b.SendBug("Something is amiss"), <- but why would you want to instantiate something this naturally global? I mean, how does that help keep something
scalable?
02 Mar, 2009, David Haley wrote in the 5th comment:
Votes: 0
staryavsky said:
Is it a good practice to combine paradigms for a potentially massive application such as a mud server?

Yes, when it makes sense to do so. It doesn't always make sense to do so.

staryavsky said:
Although a strict OO approach yields benefits in encapsulation etc, it also requires the developer to do some funky things to get it to work.

You can get encapsulation without object orientation. Object orientation that has private fields but exposes direct getters/setters isn't really encapsulating anything, although it makes it easier to set up more interesting functionality later.

staryavsky said:
A mud server is basically an I/O app

Not really. You have a whole lot of other things going on. A MUD could very well function without any players: it would basically be a simulation with a bunch of NPCs wandering around. The point isn't that this is something you'd actually do: the point is that the problem is more complex than just shuffling bytes around from socket to socket.

staryavsky said:
but why would you want to instantiate something this naturally global?

You wouldn't. :smile:
For starters, note that C# isn't actually instantiating anything. It's just accessing a function in the static class.

——

The take-home message is the same as before: using a paradigm if it helps you. Don't use it if it makes you jump through hoops needlessly. Figuring out the fine line between those is something of an arcane art that I think only comes with experience of mostly screwing things up and occasionally getting them right.
02 Mar, 2009, Stormy wrote in the 6th comment:
Votes: 0
staryavsky said:
In C# you can use 'public static' classes and it might look like this:

Bug.SendBug("Something is amiss")

Bug in this case is the name of the class. However, i'm not sure if you can do this in Ruby, and i dont see if that is desirable.

Now if you made "Bug" an instance object it might be like this:

b = Bug.new

b.SendBug("Something is amiss"), <- but why would you want to instantiate something this naturally global? I mean, how does that help keep something
scalable?


I think DavidHaley covered your questions, but to do this in Ruby you'd use a class method.

class Bug
…..
def Bug.send_bug(msg)
…..
end
end


Then, in the code, you'd create a new bug message with Bug.send_bug("Something is amiss")
02 Mar, 2009, JohnnyStarr wrote in the 7th comment:
Votes: 0
Hey, THANK YOU.

I agree with DavidHaley on the choice of choosing a paradigm.

I think most there is allot of debates out there
about OO vs. traditional programming. I think that

Stormy, i thank you as well, but i think you misunderstood
my second question. (i dont blame you, i'm really bad at asking questions)

My question wasn't how to do that in C#, it was in Ruby is there an equivelant to using "public static" methods? Or more or less Namespaces?

Instead of accessing a global function by directly calling its name, is there a way to create a namespace for it?

C# EG:

public static class Bug
{
public static void SendBug(string input)
{
blah blah blah

{
}


Somewhere else in the application:

Bug.SendBug("Something is amiss");
02 Mar, 2009, David Haley wrote in the 8th comment:
Votes: 0
What Stormy posted actually is more or less the equivalent of "public static" methods. The class 'Bug' contains nothing other than class methods that are publicly accessible, so while technically it is a class, it's really just a collection of, or namespace for, global functions.
02 Mar, 2009, Stormy wrote in the 9th comment:
Votes: 0
Well, the official way of handling namespaces in Ruby is using modules.

module A

class B

def initialize
…..
end

end

end


To create a new instance of B, you'd write A::B.new

So, if you wanted to handle your Bug example via a namespace rather than a class method, you could do this:

module Bug

def Bug.send_bug(msg)
…..
end

end

…wherever…
Bug.send_bug("Something is amiss")
02 Mar, 2009, Stormy wrote in the 10th comment:
Votes: 0
David Haley said:
What Stormy posted actually is more or less the equivalent of "public static" methods. The class 'Bug' contains nothing other than class methods that are publicly accessible, so while technically it is a class, it's really just a collection of, or namespace for, global functions.


BTW, just to clarify this – Ruby classes can contain both class and instance methods. So, for example, a Command class might have instance methods that are used by Command objects, but also a Command#load class method that's called during boot time to load all the commands.
02 Mar, 2009, JohnnyStarr wrote in the 11th comment:
Votes: 0
Oh… Ok ok, thanks.

So what does the :: symbolise?

so i dont have to instansiate the module? I gues its not a class right?

So why wouldnt this work:

module foo
def foe(msg)
….
end
end

anywhere else:

foo.foe("hello!") <- would ruby recognize this?

foo::foe("hello") <- could you explain this syntax? thanks!
02 Mar, 2009, David Haley wrote in the 12th comment:
Votes: 0
x::y means "y in the module x", x.y means "y in the class x".

By the way, you don't have to instantiate a class to use class methods. Think of class methods as static methods: they're methods that don't apply to individual instances but to the whole class.
02 Mar, 2009, Stormy wrote in the 13th comment:
Votes: 0
Both actually work…

module Bug

MSG = "Something is amiss"

def Bug.send_bug
p MSG
end

end

Bug::send_bug => "Something is amiss"
Bug.send_bug => "Something is amiss"
p Bug::MSG => "Something is amiss"
p Bug.MSG => undefined method `MSG' for Bug:Module (NoMethodError)


The dot operator is considered the proper method for calling a module method (sorry, used the wrong syntax earlier, though it does work). The colons should be used to reference module constants. Also, note that I had a typo in my earlier example (fixed it) – you include the module name in method declarations within a namespace module.
02 Mar, 2009, kiasyn wrote in the 14th comment:
Votes: 0
If you're actually working on Bugs and stuff and not just using it as an example I highly recommend the log4r ruby gem.
02 Mar, 2009, JohnnyStarr wrote in the 15th comment:
Votes: 0
THANKS, best answer yet!
03 Mar, 2009, Vassi wrote in the 16th comment:
Votes: 0
I had a well thought out, quoted and point by point post. Then I hit backspace and firefox went back a page, losing it. Being already bitter about that, I hope this doesn't sound more pointed than I intend, so forgive me if it does.

In short, it seems to me you don't really understand OO design and you're looking for excuses not to use it. The answer to your questions is: go with what you already know. A MUD is not a trivial I/O project, if you think of it that way you will fail (sorry, but you will). Taking on something like this, from scratch or near to, with a language or design paradigm that you're not familiar with will end badly.

Lastly, the example you gave with a static class in C# is in fact funky because you would never do that. If SendBug is meant to report to the player, it would be a method on the player's object or the player's connection object. A class is more than a collection of values, it sounds like you're thinking of them as bags of settings that you need static methods to do stuff with. A class should encompass all of the settings and any related functionality that that object represents. You very seldom end up needing static methods except for things that get used in more than one place, like math utility functions or database operations.
03 Mar, 2009, Tyche wrote in the 17th comment:
Votes: 0
staryavsky said:
Is there a better way to do this?:

Rocket mud has a global function called "bug" so if something bombs, you can put in a (rescue) keyword to send a message to the bug.txt file:


There's really no such thing as a global function in Ruby. You are actually defining an instance method on Object, which is then inherited by every class. The context of everything outside a class is "main", which is an instance of Object. You can test this in RocketMud because all these work.
bug "a bug"
Object.bug "a bug"
Mobile.bug "a bug"


irb(main):041:0> def bug
irb(main):042:1> puts self.class
irb(main):043:1> end
=> nil
irb(main):044:0> bug
Object

staryavsky said:
Bug.SendBug("Something is amiss")

Bug in this case is the name of the class. However, i'm not sure if you can do this in Ruby, and i dont see if that is desirable.


As Skol mentioned class methods can be defined with:
class A
def A.foo
,,,
end
end

You can also use:
class A
def self.foo
,,,
end
end

…as self in the context of class is the class. This is usually preferable because if you want to change the name of the class, you only have to do it in one place.
03 Mar, 2009, elanthis wrote in the 18th comment:
Votes: 0
Vassi said:
Lastly, the example you gave with a static class in C# is in fact funky because you would never do that. If SendBug is meant to report to the player, it would be a method on the player's object or the player's connection object. A class is more than a collection of values, it sounds like you're thinking of them as bags of settings that you need static methods to do stuff with. A class should encompass all of the settings and any related functionality that that object represents. You very seldom end up needing static methods except for things that get used in more than one place, like math utility functions or database operations.


I personally disbelieve that OO is the only proper way to design software. Sometimes procedural programming is just what makes the most sense for the task at hand. Sometimes functional programming is what I need to get the job done quickly and efficiently. Declarative programming can be quite useful in various contexts too. AI is often most easily represented as a mix of actor programming and imperative programming. Let's not forget the power of generic programming, either.

Bjarne Stroustrup (original inventor of C++) had some good arguments about the multi-paradigm approach. He talked about why the std::string class does not have toupper() or substr() methods or anything of the sort. His basic argument is that methods like that aren't best conceptualized as methods (which are conceptually signals sent to a receiver to invoke a transition), but are instead very naturally thought of in a procedural (or even functional context). Operations like toupper() are very simply represented as a pure function, because they take an input and return an output with no side effects. Tacking procedural/functional operators into an OO model doesn't actually provide any real advantages, so why do it?

If you look at most C# or C++ code, a lot of the time classes are used in a very non-OO way. Most singleton objects are generally just procedural code with encapsulation; the exact same functionality could be implemented (sometimes more cleanly) in purely-procedural code. It's not until you start needing inheritance or polymorphism that OO really offers any advantages over other paradigms. (You can encapsulate and modularize just fine in most decidedly non-OO languages, thank you.) It's not at all uncommon to "abuse" classes and objects to work around limitations of the expressiveness of the language rather than developing truly OOP solutions. For example, many MUDs create commands as objects inheriting from a Command base class; this is done just as a way to register callbacks with specific command names, and not because the command objects are actually truly OOP constructs. Often that is done either because using classes like that is easier (less typing), because the language lacks reflexive capabilities (like C++), or because the reflexive capabilities of the runtime are slow and cumbersome (like C#).

So… point is, there's nothing wrong with just having a bug function. If the function is meant to mutate instances of a specific class, then it should be a method. If it's just a routine that takes some input (including maybe certain objects) and then performs some operation (like send an email or insert a row into a table), then it makes perfect sense to make it just a 'static' function.
03 Mar, 2009, David Haley wrote in the 19th comment:
Votes: 0
Basically, in the end of the day, use the paradigm that's right for the job. It's kind of silly to force everything into a single paradigm. Different paradigms exist because they are good at different things.

The thing is that, as I said earlier, making these decisions comes with years and years of experience. When starting to program, it can make sense to follow a model because at least the model has a lot of thought put into it, even if it isn't right for everything. As time goes on, you can start spotting its flaws. But don't mistake "oh, I don't feel like doing that, it looks ugly" with "it's a legitimate flaw in the paradigm".
03 Mar, 2009, Vassi wrote in the 20th comment:
Votes: 0
elanthis said:
Bjarne Stroustrup (original inventor of C++) had some good arguments about the multi-paradigm approach. He talked about why the std::string class does not have toupper() or substr() methods or anything of the sort. His basic argument is that methods like that aren't best conceptualized as methods (which are conceptually signals sent to a receiver to invoke a transition), but are instead very naturally thought of in a procedural (or even functional context). Operations like toupper() are very simply represented as a pure function, because they take an input and return an output with no side effects. Tacking procedural/functional operators into an OO model doesn't actually provide any real advantages, so why do it?


Funny story, C# 3.0 added Extension methods. These are basically static methods, on a static class, that are designed to look like local methods on a class. With these you could do something like declare a StaggerCase method on string objects so that you can make every string 'rEaD lIkE tHiS' if you wanted to simply by saying myString.StaggerCase().

The inclusion is still debated by a lot of people. On the one hand it could lead to bad habits if you vomit out a bunch of static extension classes, but on the other it can make tedious code a bit more easy to write and a bit more readable. The biggest strength is the ability to extend any class, including system classes. The biggest weakness, unfortunately, is the same. It can become easy to lose track of which methods are local and which ones are extended.

Anyway, just thought I'd add that in as I thought of them when I read that. Also, I don't believe I implied - or meant to imply - that OO is the one to rule them all, I certainly agree that each method has its strengths and uses.
0.0/66