View Full Version : Design Patterns
tentons
08-10-2004, 04:46 AM
I'm creating a component-based object model so that I can put game objects together at run time by using individual pieces with specific functionality (like input, rendering, collision detection, etc). I'm using the Composite and Factory patterns. Eventually I want to have plug-ins for adding new objects dynamically (ie, expansion packs and/or user content), but for the sake of finishing sooner rather than later, I am not pursuing that yet.
My inter-object communications system uses the Observer and Context patterns, which is working out well.
What, if any, design patterns have you used in your technical designs, and what features did they help you to create?
Do you find that "formal methods" definitely help reduce time to completion and improve the quality of your code? Or is it overkill for a typical indie game?
svero
08-10-2004, 05:37 AM
I don't think you could say it's overkill or not simply based on the idea that you're developing an indie game. IMHO The guide for this sort of thing is always what you're trying to accomplish. It's the program itself. It might be overkill if I could say for instance that a game engine doesn't really require this kind of plug n play interface. Or maybe it does. It really comes down to why you're using the pattern.
Some people use design patterns and UML etc...for the sake of using them or because they just read a book on the subject. Other better developers will happen apon a design pattern and not know it because it happened to be the solution that fit what they were doing.
Being familiar with design patterns is not a bad thing. There are common one's because to some extent the same problems need to be solved often and the same kinds of solutions are useful. But IMO your goal as a developer should always be to make the simplest nicest interface you can. Sometimes that's a design pattern and sometimes it's a trick using the c++ preprocessor.
tentons
08-10-2004, 10:30 AM
My biggest reason for using them is that they often solve the problem I'm tackling very well, and many times they help put related things into perspective. One of my goals is to create a re-usable engine core, so if I can meet that goal in a more robust way by thinking in terms of patterns and high-level design, then that's got to be good.
And, I'm just curious about the programming habits of other indie developers. :)
HairyTroll
08-10-2004, 12:02 PM
My biggest reason for using them is that they often solve the problem I'm tackling very well
Here the problem is one created by the language you are using. Design patterns are created to get around the limitations imposed by the language e.g. C++ (or Java, take your pick).
Design Patterns In Dynamic Programming (http://c2.com/cgi/wiki?DesignPatternsInDynamicProgramming) 16 of the 23 patterns in Design Patterns were "invisible or simpler" in Lisp
And here Lisp can safely be replaced by any dynamic language (OCaml, Python, Perl, Haskell, Dylan)
Imagine spending all that time on your game instead of having to write all those design patterns.
I'll get off my soapbox now...
mathgenius
08-10-2004, 02:25 PM
Most recently I used a proxy pattern to capture control signals to the Hero. It has allowed me to implement record/playback functionality which is good for testing etc. What I liked about this was that any future changes in the interface to the Hero will automatically be accounted for in the proxy.
I did this in python, and while it may be true that a lot of the patterns are "one liners" in this language, it still pays to think in these terms. I am now thinking about a similar kind of proxy trick for the Pen class of the level editor. This is so that undo/redo code is separated from the Pen code.
I dont think this stuff is particularly formal... It's more about self documenting code: I have a class called Proxy that does some funky things, but you can nut it out if you think in terms of proxying etc.
But, I do have two hats: the hacker hat and the more thoughtful hat. I switch between hats regularly, because it's often not possible to guage the success of a design decision until one has banged together some code to create a shambles.
Simon.
Mithril Studios
08-10-2004, 04:10 PM
I agree with HairyTroll; most patterns really are just a way to deal with "shortcoming" of a language.
As to using formal methods, I do look for ways to apply that design mindset to my code, but to be honest I still have room for improvement. The capabilities of Eiffel to trivially support pre & post conditions & invariants is one of the major reasons why I love working with the language.
Anthony
Aldacron
08-10-2004, 06:07 PM
Patterns aren't something which deal with shortcomings of a language. There are design patterns which apply regardless of the language you use, and conversely some are dependant upon language features. The quote regarding Lisp refers specifically to the patterns described in the GoF book, not patterns in general. There are probably other design patterns which are more common in Lisp (I wouldn't know, as I've never used it).
Before the term 'Design Patterns' was coined, people were using them. Someone didn't just sit down one day and create a set of design patterns. Instead, commonly used solutions to common programming problems were recognized and documented. From the GoF preface:
Design patterns capture solutions that have developed and evolved over time. Hence they aren't the designs people tend to generate initially. They reflect untold redesign and recoding as developers have struggled for greater reuse and flexibility in their software.
That's why they're called design 'patterns'. Patterns are something which can be recognized after the fact. People look for patterns in different capacities all the time (police, economists, politicians, for example) and once you know what the common patterns are in a particular field they become more easily recognizable. In the case of software design, knowing common (and useful) design patterns can save you a great deal of time in refactoring/redesigning a project. You are able to apply known design concepts from the beginning rather than deriving them on your own over several iterations of code.
tentons
08-10-2004, 06:36 PM
@Aldacron, I agree. What I find most interesting is how you can almost think in terms of patterns and nothing else in some situations (ie, at a sufficiently high level of the design). Most of it transcends syntax. Whether you can more easily implement it in language X is a religious debate and relatively unimportant to the larger picture of OO design.
So maybe one day there will be a meta language for designing at that higher level, which would be lots of patterns mixed with something else. Maybe it exists already, and I don't know about it. :) UML, perhaps?
@mathgenius, speaking of "hacker hats," I recently found it very helpful to use pseudo-code to elaborate the details of a specific implementation. I read about the PDL (Program Design Language) in McConnell's Code Complete (http://www.amazon.com/exec/obidos/ASIN/0735619670/qid=1092191680/sr=2-1/ref=sr_2_1/104-0333797-6923119) but never chose to use it.. but now I've found myself using something similar unconsciously, and it really helps to expose details that patterns don't or can't help you with (like interfacing between your particular set of objects).
Together these add up to a set of design tools that have been very helpful to me recently, because one addresses high level design and the other helps bash out details of the implementation for that high level design.
svero
08-10-2004, 08:25 PM
Yeah you could use LISP and avoid factory patterns or something like that, but then of course you'd have to use LISP?!? That's like taking the rusted 70's vw beetle to a drag race because the leather in your ferrari is tattered in one seat corner. If I never see another line of LISP so long as I live it will be too soon.
(((((((((((((((((((((((((((((((((((((((lisp) sucks))))))))))))))))))))))))))))))))
Someone check my bracketing.
- S
Diodor Bitan
08-10-2004, 09:29 PM
Original post by svero
Yeah you could use LISP and avoid factory patterns or something like that, but then of course you'd have to use LISP?!? That's like taking the rusted 70's vw beetle to a drag race because the leather in your ferrari is tattered in one seat corner. If I never see another line of LISP so long as I live it will be too soon.
Actually, it would be more like taking your 70's F16 fighter to a drag race, if Common Lisp wasn't a modern language, standardized in the mid 90's (as opposed to many other languages in the LISP family, which were around for much longer).
Someone check my bracketing.
Why should I, every Lisp IDE no matter how simple will automatically do that for you. I'm still a relative Lisp newbie (although the most complicated program I wrote so far was in Lisp - because of Lisp), but the syntax and the parenthesis are not only not a problem, they are significantly nice. And that's before going into Lisp macros.
HairyTroll
08-10-2004, 10:49 PM
What I find most interesting is how you can almost think in terms of patterns and nothing else in some situations (ie, at a sufficiently high level of the design). Most of it transcends syntax. Whether you can more easily implement it in language X is a religious debate and relatively unimportant to the larger picture of OO design.
I never intended this to become a debate on Lisp as that always tends to immediately polarize the discussion. (F-16 fighters, drag racing, B52 bombers, nukes, Spectrum vs C64, Atari vs Amiga etc.) My point was that using a language that forces one to build a huge infrastructure in which to implement even a simple pattern is in itself limiting.
What you said:
I'm creating a component-based object model so that I can put game objects together at run time by using individual pieces with specific functionality (like input, rendering, collision detection, etc). I'm using the Composite and Factory patterns. Eventually I want to have plug-ins for adding new objects dynamically (ie, expansion packs and/or user content), but for the sake of finishing sooner rather than later, I am not pursuing that yet.
My inter-object communications system uses the Observer and Context patterns, which is working out well.
I count 4 patterns right there. How long did that take you to write/will it take you to write? 10 minutes? 1 hour? 1 week part time?
Say you spent 1 week completely implementing, testing and debugging your vision (plug-ins for adding new objects dynamically (ie, expansion packs and/or user content). Say it weighs in the order of 2000 lines of C++ code.
Say it took someone working in Python* 3** hours to do the same thing in 150 lines of code. Now you have just spent 1 week implementing those patterns in C++. The Python guy spent 3 hours using those same patterns to solve a problem and implement additional functionality. In C++ the pattern becomes a mini-project. In Python the implementation of the pattern isn't even a blip on the radar.
*And here, replace Python with any functional/dynamic language.
**This is a thumb suck.
So maybe one day there will be a meta language for designing at that higher level, which would be lots of patterns mixed with something else. Maybe it exists already, and I don't know about it. :) UML, perhaps?
You know, it's funny you should mention meta languages in a thread derailed by Lisp. :) Lisp is known as the language to write other languages.
MiCo Games
08-10-2004, 11:42 PM
But this is really a separate discussion from that of patterns. How long a specific pattern takes to implement in one language vs another might be an interesting discussion, but it's got nothing to do with the question of whether using a design pattern helps in saving you time or not, whether it improves quality or not.
In my opinion, using patterns can help in both saving time and improving quality, regardless of language. It doesn't necessarily means using formal patterns described in books, it can just as well be from your own collection of patterns. The longer you program, the more experienced you get, and eventually you'll find that you have a bunch of fixed solutions for problems that keep reoccuring, and that you tend to solve them in a very similar way each time. That's your own patterns right there, and by making good use of them you can get your code done sooner, as you don't have to sit around thinking "Hmm, how do I best solve this...". Instead, you can do it like you've always done it.
Reading up on design patterns can really help in building your own set of patterns you are comfortable with, or getting rid of some flaws in the ones you are using. But I don't think you should go looking for a design pattern for every problem you encounter.
Nemesis
08-10-2004, 11:46 PM
I've had formal training on functional languages, using Lisp as an example and was even exposed to its underlying theory, something called Lambda Calculus.
While I did find it intellectually entertaining, I failed to see the practicality of it. I mean it's all about functions after all. I personally find the OOP paradigm to be way more practical especially when it comes to designing a solution that models entities interacting with each other in real time, more specifically games.
Actually I know of at least one game written in a functional language called Clean. The game is Mike Wiering's Sint Nicolaas.. check it out here:
http://sint.sourceforge.net/
Just so I don't derail the thread further: I actually find myself using Factory and Singleton patterns often and I'm recently using Observer and Model-View-Controller. I guess like most of you I end up using patterns unwittingly, if not to the full extent as discussed by the GoF.
Diodor Bitan
08-11-2004, 12:14 AM
Original post by HairyTroll
I never intended this to become a debate on Lisp as that always tends to immediately polarize the discussion.
Noone here is using Lisp for their indie games (I would really hope to be wrong on this one), so I suppose things will not escalate way above poking jokes around.
You know, it's funny you should mention meta languages in a thread derailed by Lisp. Lisp is known as the language to write other languages.
One could say Lisp macros are design patterns expressed in Lisp code.
Original post by Nemesis
I've had formal training on functional languages, using Lisp as an example and was even exposed to its underlying theory, something called Lambda Calculus. While I did find it intellectually entertaining, I failed to see the practicality of it.
Yep, me too. Lisp (and even more so Scheme) are perfect to perform acts of magic to confuse students with. That that class focuses on functional programming and Lambda Calculus and not on pratical issues doesn't mean Lisp isn't a practical language (it is).
In fact, Lisp is not (necessarily) functional, and it supports OOP as well as procedural programming. Macros make it truly multi-paradigm.
svero
08-11-2004, 12:27 AM
Why should I, every Lisp IDE no matter how simple will automatically do that for you. I'm still a relative Lisp newbie (although the most complicated program I wrote so far was in Lisp - because of Lisp), but the syntax and the parenthesis are not only not a problem, they are significantly nice. And that's before going into Lisp macros.
Well i was just poking a bit of fun. By all means use Lisp if you think it's good. In fact I'd like to encourage all my competitors to switch to Lisp! Scheme if you prefer! Use Lambda functions to your hearts content! Please please switch to Lisp.
Personally I find it a horrid language so, as imprefect as it is, I will stick to ++ for the time being.
Diodor Bitan
08-11-2004, 12:48 AM
Original post by svero
Well i was just poking a bit of fun. By all means use Lisp if you think it's good. In fact I'd like to encourage all my competitors to switch to Lisp! Scheme if you prefer! Use Lambda functions to your hearts content! Please please switch to Lisp.
:)
Seriously though, I'm tempted to do just that. :rolleyes: In the mean time, I have to be satisfied with my current Lua + C combination.
tentons
08-11-2004, 03:44 AM
@HairyTroll: I don't doubt that LisP is a capable language, but I do have to question the pragmatism of choosing it for a commercial game project, which is the context here.
<flame bait, apologies in advance, but I honestly am curious>
Having said that, can a plug-in based game engine (entire engine--not just a subsystem--that is also performant) like I described be created in Python only in several hours?? What about distribution issues? Ease of use for customers? Graphics/sound/input capabilities? Integration with 3rd party vendor services? I have no experience with Python, but if it really can do everything C++ can, but faster productivity-wise, maybe I should look into it.
</flame bait>
More pertinent to the thread, in my experience design patterns don't cause extra development time. If anything, they save you time at the design phase. Coding them is fairly straight-forward.
And though maybe not always the simplest (that's a relative term, I'm guessing), I do prefer to avoid ugly things like call-backs and function tables, which are perhaps more "to the metal" (does that make it simpler?) but less OO. I'd rather not deal with function pointers when I'm constructing or maintaining code. Java taught me a lot about good OO design.
@Wayward: I consider maintenance and extensibility big issues, as it will save time later--and time is money since getting done faster means less delay leading up to sales.
And, at the risk of sounding religious, I don't think all indie games have to be pac-man-clone-simple. I hope to typify the antithesis of that, actually. My first game won't be all that ambitious, but I don't plan to release what might be considered "typical" indie games, especially as I build on previous projects. So, I feel justified making the extra effort to build something more complex (if, in fact, design patterns add any complexity, which I would categorize as debatable) that will last longer in the language I chose to use.
At the end of the day it boils down to personal choice (as with any art form), but my original intent was to find out who else chose to use design patterns and how it helped them do better work and do it quicker.
Aldacron
08-11-2004, 05:20 AM
Patterns are useful if you are designing a self-regulating C++ library for others to use, with an interface that doesn't break after upgrades, or you're working with other peoples class libraries without source. For indie development, patterns smell (http://c2.com/cgi/wiki?CodeSmell) of over-engineering.
I disagree. Over-engineering happens when you take things to the extreme. Applying patterns where they are useful is not in and of itself extreme. This really pays off when you want to resuse your base code, and even for maintenance. For example, even if you don't intend to support both D3D and OpenGL, or more than one audio API at a time, using abstract interfaces with Factories will allow you to rip out and replace core systems easily when you later want to upgrade.
My philosophy is, libraries I write for myself should meet the same design standards they would if I were creating them for public use. How easy my libs are to use/extend/maintain is every bit as important to me as it would be to other clients. Besides, you never know when the Open Source bug might hit you. I don't have the genius of Carmack, so I have nothing to offset the criticism of messy code :)
dogbert
08-11-2004, 07:04 AM
@HairyTroll: I don't doubt that LisP is a capable language, but I do have to question the pragmatism of choosing it for a commercial game project, which is the context here.
Naughty Dog use a LISP like language for their in-game scripting & development, and most of the logic for the Jak games is written in LISP because of that.
Jim Buck
08-11-2004, 07:40 AM
@tentons: re: Python
I've only recently begun looking into the language, but I've read a lot about it already. If you are really curious, I recommend reading "Learning Python" O'Reilly book first. It gives a really good understanding of the language both under and over the covers. "Dive Into Python" is a good follow-up book for more complex examples (and is free on the website). Also, reading all the FAQs on Python.org as well as the documentation of integrating C/C++ and Python together into one happy family.
To answer your questions..
Distribution issues - there are several options for creating a fully-contained .exe out of your Python code so the user doesn't have to have Python themselves installed.
This also answers the ease-of-use for customers, but I do wonder how well Python performs on slower hardware. (There are some good articles on optimization, though, and you can always code up key pieces of your Python code into C/C++ for speedup.)
Graphics/sound/input capabilites - there are tons of libraries you can use with Python that are ready to go (OpenGL for example).
I'm not sure what you mean by integration with 3rd party vendor services.
tentons
08-11-2004, 11:19 AM
This also answers the ease-of-use for customers, but I do wonder how well Python performs on slower hardware. (There are some good articles on optimization, though, and you can always code up key pieces of your Python code into C/C++ for speedup.)
That's really interesting, but I shouldn't be surprised since I know you can do similar things with Java (hooking it to C++ or whatever language). There's got to be a way to marry the productivity of such a language with the low-level power of C++. I guess, as dogbert mentioned, maybe you could use it for game logic and other such sections.
I'm not sure what you mean by integration with 3rd party vendor services.
For example, Plimus offers their "Plimware" to help with registration issues. But if you can hook Python to C++, then that's not much of an issue, is it? :)
Thanks for the tips, I will check it out.
Kai Backman
08-11-2004, 11:23 AM
:)
As Gamma et. al. point out, the Design Patterns book is just a catalogue of things existing. It is an approach to observe programmers in the wild in contrast to steering them in a specific direction. Having a name for a habit just makes it easier to communicate (the main purpose of UML as well).
Lisp defines a tight semantic base for a language, a way how symbols should be combined to form meaning. It is comparable in tightness to original C, but the domains are different (and both are complete in a Turing sense). The base domain of C is close to how modern hardware functions while Lisp is close to symbol processing. Both work in their respective domains exceptionally well.
Arguing that many design patterns don't apply in Lisp is a bit like a farmer saying that his tools are superioir because they don't include lines, hooks and poles. A fisherman would disagree.. :)
I think functional languages are good for gameplay related programming. Languages like Lua, Scheme, Python, Ruby, have a short roundtrip time, closed (non crash) interactive environments and simple syntax. Even an expert programmer can benefit from these features while tweaking gameplay. C++ again has a robust feature set for defining this language of gameplay in terms of underlying hardware. My policy is to use C++ to define the "verbs" and "nouns" and Lua to write the phrases, paragraphs and chapters. Both are equally important for a good game.
Oh, and I actually like both C/C++/Java and Lisp/Scheme even after having programmed them for over a decade... (And programmed games in both) ;)
Jim Buck
08-11-2004, 02:33 PM
That's really interesting, but I shouldn't be surprised since I know you can do similar things with Java (hooking it to C++ or whatever language). There's got to be a way to marry the productivity of such a language with the low-level power of C++. I guess, as dogbert mentioned, maybe you could use it for game logic and other such sections.
Even more interestingly, you can approach the C++-with-Python from both sides:
1) You can code a C++ program, link in the Python interpreter, and have your C++ program execute Python scripts.
2) You could create a C++ "plugin" that your Python scripts would import (in the same way you would import other Python scripts), and those scripts can call the C++ code as though it's "native" Python script - your Python code can even use and inherit from classes that you are creating in your C++ code.
.. or you could even mix the two.
For example, Plimus offers their "Plimware" to help with registration issues. But if you can hook Python to C++, then that's not much of an issue, is it? :)
Ahh, yes, you would have to mix the two in order to make it work.. but it should theoritically work (disclaimer since I don't actually have Python experience beyond recently installing it and reading the two books and FAQs I mentioned earlier).
icosahedron
08-11-2004, 09:16 PM
Design Patterns are great. The book is definitely one of the classics of the field.
Naughty Dog use a LISP like language for their in-game scripting & development, and most of the logic for the Jak games is written in LISP because of that.
Lisp was also one of the negatives pointed out in the Post Mortem column done on Jak & Daxter in Game Developer (can be found on Gamasutra.com).
Still, I'm using it, Corman Lisp to be specific. It supports Common Lisp and direct to native code compilation as fast as any other compiler I've ever seen. It also has a decent enough FFI (foreign function interface) for Windows and COM, and it's hard to go back to single parameter polymorphism when you've used multimethods.
I've been tempted to switch to Python though, as it is a neat language and supports C++ FFI very well through the Boost.Python library. It also has very good library support and has been proven on several large projects. My only concern with it is performance, but the Parrot VM that will support it is running Python code about 1.5x faster than the CPython VM is currently, though the Parrot VM is not yet complete.
Do you find that "formal methods" definitely help reduce time to completion and improve the quality of your code? Or is it overkill for a typical indie game?
Writing software is like writing English (or whatever your language of choice is). Some people can just sit and write, and then they have to revise. Others take a more formal approach with outlines, character backgrounds, and plot summaries before they can "flesh it out." It's a matter of taste and style. I for one prefer a little more formality. I develop a module for my software to a point that I can write an article about it. Once I can write an article explaining how to use it and how it works, then I consider it fit for use. I'm just finishing my serialization module and will start the article to "document" it very soon.
My only caveat about myself is that I've not shipped a game yet, so my words aren't to be heeded as proven experience. :)
As Gamma et. al. point out, the Design Patterns book is just a catalogue of things existing. It is an approach to observe programmers in the wild in contrast to steering them in a specific direction. Having a name for a habit just makes it easier to communicate (the main purpose of UML as well).
[...]
Indeed. Another thing I like about design patterns is that it's easier to pickup code from others. "others" also means yourself, if you get back to your code a year later. It's similar to coding conventions for that matter.
vBulletin v3.6.0, Copyright ©2000-2008, Jelsoft Enterprises Ltd.