From: brett l. <wak...@gm...> - 2008-09-01 22:37:44
|
I just wanted to send a quick update to the list on new developments. I've decided to get started on a client/server version of Rails. It's been far too long since I actively wrote code, and I feel like I should be more actively developing Rails. I've been giving it some thought, and I think the best approach is to write a new architecture (mostly) from the ground up, rather than migrating our existing code into a client/server paradigm. There are several reasons why I want to incorporate refactoring the code into adding such a major new feature. One of the primary reasons is that it will give me a chance to revisit the UI, the hex drawing code, and many other areas of the codebase, and look at these things with a fresh perspective. It's also a chance to clean up and organize the code in ways that are difficult currently. One thing that I want to make perfectly clear. I'm absolutely not throwing out our existing code. What I _am_ doing is starting from a new, empty project directory on my workstation, writing a basic client and server, then slowly moving our existing code in, one piece at a time. During this process, I'll be cleaning up many areas of the code, and rewriting a couple of things from scratch. As soon as I have a basic framework, I'll publish a new module into CVS so that everyone can jump in and help get network play fully functioning. ---Brett. |
From: Erik V. <eri...@hc...> - 2008-09-02 22:04:33
|
Hi Brett, I'm very interested to see what you will come up with. In all honesty, Rails has perhaps become a bit too much my own baby, and a fresh look way well be in order. You're also solving my dilemma on how to continue myself - in the near future I will now just keep adding more games to the existing code. Of course, I have my own thoughts on how to achieve the client/server split, and as you know I have already been working somewhat towards it. For instance, I think you would do well to reuse the PossibleAction hierarchy, to pass allowed and executed actions forth and back between client and server (in some serialized form). On the other hand, the screen updates via the ModelObject/ViewObject hierarchies do not translate well; the subclasses can perhaps be retained, but the top classes need be redone as the underlying Observer/Observable pattern must be replaced by something completely different. I don't yet have a conceptual solution for that. Although these are the main aspects of the client-server communication, there is a lot more that I have not even started to think about (such as changes to the current player and phase). Anyway, I'll be happy to discuss such matters in more detail if you like, but perhaps we can then better do that off-list, to avoid annoying the onlookers. I appreciate that you want to keep this new approach separate from the existing code. Hopefully we can reintegrate later on. Good luck, Erik. > -----Original Message----- > From: rai...@li... > [mailto:rai...@li...] On Behalf > Of brett lentz > Sent: Monday 01 September 2008 23:38 > To: Development list for Rails: an 18xx game > Subject: [Rails-devel] Starting on a client/server > > I just wanted to send a quick update to the list on new developments. > > I've decided to get started on a client/server version of Rails. It's > been far too long since I actively wrote code, and I feel like I > should be more actively developing Rails. > > I've been giving it some thought, and I think the best approach is to > write a new architecture (mostly) from the ground up, rather than > migrating our existing code into a client/server paradigm. > > There are several reasons why I want to incorporate refactoring the > code into adding such a major new feature. One of the primary reasons > is that it will give me a chance to revisit the UI, the hex drawing > code, and many other areas of the codebase, and look at these things > with a fresh perspective. It's also a chance to clean up and organize > the code in ways that are difficult currently. > > One thing that I want to make perfectly clear. I'm absolutely not > throwing out our existing code. > > What I _am_ doing is starting from a new, empty project directory on > my workstation, writing a basic client and server, then slowly moving > our existing code in, one piece at a time. During this process, I'll > be cleaning up many areas of the code, and rewriting a couple of > things from scratch. > > As soon as I have a basic framework, I'll publish a new module into > CVS so that everyone can jump in and help get network play fully > functioning. > > > ---Brett. > > -------------------------------------------------------------- > ----------- > This SF.Net email is sponsored by the Moblin Your Move > Developer's challenge > Build the coolest Linux based applications with Moblin SDK & > win great prizes > Grand prize is a trip for two to an Open Source event > anywhere in the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel > |
From: Brett L. <wak...@gm...> - 2008-09-02 23:21:25
|
Sounds like an excellent plan. I'm rather happy that you've taken so much on. It would have taken me a lot longer to implement most of the things that you took on. :-) Here's how I'm envisioning the architecture: We need 4 main components: Client, Server, Game Engine, and Data Transport. These fit fairly well into the Model, View, Controller paradigm, which I'm happy about. I'm going to attempt to make everything as modular as possible to allow us to build multiple modules (e.g. Swing Client, and Web Client. Java Sockets, Jabber, SMTP transports, etc.). However, what this means is that we're going to need to get better about writing JavaDoc and being a bit more strict with our API definition so that we don't break things as we build additional modules. Right now, the biggest downside I can foresee is that _all_ clients must talk to the server over a transport, which means that even local games will have to load up the network bits and talk across the localhost. It's a minor amount of overhead, though. So other than the conceptual inefficiency, I don't think it's a major problem. The main requirement is that the Server will need two methods of startup: a command-line no-GUI method, and through the Options GUI for hosting a local Client and Server. For now, I've decided to just use the native Java sockets in java.net.* and java.nio.*. I'll push PBEM support off until the basic architecture is more fleshed out. My gut feeling is that real-time network play should be the higher priority because there are already workable PBEM solutions. I think that maintaining good component separation is going to require that we adopt Java's concept of events and listeners. We do that to some extent with the Observer objects, but I think it's definitely something that we can work on improving. ---Brett. > -----Original Message----- > From: rai...@li... [mailto:rails-devel- > bo...@li...] On Behalf Of Erik Vos > Sent: Tuesday, September 02, 2008 3:05 PM > To: 'Development list for Rails: an 18xx game' > Subject: Re: [Rails-devel] Starting on a client/server > > Hi Brett, > > I'm very interested to see what you will come up with. In all honesty, > Rails > has perhaps become a bit too much my own baby, and a fresh look way > well be > in order. You're also solving my dilemma on how to continue myself - in > the > near future I will now just keep adding more games to the existing > code. > > Of course, I have my own thoughts on how to achieve the client/server > split, > and as you know I have already been working somewhat towards it. For > instance, I think you would do well to reuse the PossibleAction > hierarchy, > to pass allowed and executed actions forth and back between client and > server (in some serialized form). On the other hand, the screen updates > via > the ModelObject/ViewObject hierarchies do not translate well; the > subclasses > can perhaps be retained, but the top classes need be redone as the > underlying Observer/Observable pattern must be replaced by something > completely different. I don't yet have a conceptual solution for that. > Although these are the main aspects of the client-server communication, > there is a lot more that I have not even started to think about (such > as > changes to the current player and phase). > > Anyway, I'll be happy to discuss such matters in more detail if you > like, > but perhaps we can then better do that off-list, to avoid annoying the > onlookers. > > I appreciate that you want to keep this new approach separate from the > existing code. Hopefully we can reintegrate later on. > > Good luck, > Erik. > > > -----Original Message----- > > From: rai...@li... > > [mailto:rai...@li...] On Behalf > > Of brett lentz > > Sent: Monday 01 September 2008 23:38 > > To: Development list for Rails: an 18xx game > > Subject: [Rails-devel] Starting on a client/server > > > > I just wanted to send a quick update to the list on new developments. > > > > I've decided to get started on a client/server version of Rails. It's > > been far too long since I actively wrote code, and I feel like I > > should be more actively developing Rails. > > > > I've been giving it some thought, and I think the best approach is to > > write a new architecture (mostly) from the ground up, rather than > > migrating our existing code into a client/server paradigm. > > > > There are several reasons why I want to incorporate refactoring the > > code into adding such a major new feature. One of the primary reasons > > is that it will give me a chance to revisit the UI, the hex drawing > > code, and many other areas of the codebase, and look at these things > > with a fresh perspective. It's also a chance to clean up and organize > > the code in ways that are difficult currently. > > > > One thing that I want to make perfectly clear. I'm absolutely not > > throwing out our existing code. > > > > What I _am_ doing is starting from a new, empty project directory on > > my workstation, writing a basic client and server, then slowly moving > > our existing code in, one piece at a time. During this process, I'll > > be cleaning up many areas of the code, and rewriting a couple of > > things from scratch. > > > > As soon as I have a basic framework, I'll publish a new module into > > CVS so that everyone can jump in and help get network play fully > > functioning. > > > > > > ---Brett. > > > > -------------------------------------------------------------- > > ----------- > > This SF.Net email is sponsored by the Moblin Your Move > > Developer's challenge > > Build the coolest Linux based applications with Moblin SDK & > > win great prizes > > Grand prize is a trip for two to an Open Source event > > anywhere in the world > > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > > _______________________________________________ > > Rails-devel mailing list > > Rai...@li... > > https://lists.sourceforge.net/lists/listinfo/rails-devel > > > > > ----------------------------------------------------------------------- > -- > This SF.Net email is sponsored by the Moblin Your Move Developer's > challenge > Build the coolest Linux based applications with Moblin SDK & win great > prizes > Grand prize is a trip for two to an Open Source event anywhere in the > world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |
From: Erik V. <eri...@hc...> - 2008-09-03 21:34:52
|
> Right now, the biggest downside I can foresee is that _all_ > clients must > talk to the server over a transport, which means that even > local games will > have to load up the network bits and talk across the > localhost. Not necessarily, in my opinion. I had in mind generic API's (interfaces) at the client and the server side, that would take any sequence of objects at one side and deliver them at the other side. How that is done is internal to the transport module, that could have several implementations. For local play, it is just pass-through; I don't think we need separate programs communicating through a socket. For a client/server connection through sockets, the objects would be serialized at one side, sent over the socket, and deserialized at the other side (each object must know how to (de)serialize itself). For PBEM, we have SMTP and POP3 as transport mechanisms (in this case the objects must be accompanied by text). Etc. My approach would have been first to refactor the current code to this architecture, and then add the transport through sockets as would just be a new implementation of an interface. > It's a minor > amount of overhead, though. So other than the conceptual > inefficiency, I > don't think it's a major problem. The main requirement is > that the Server > will need two methods of startup: a command-line no-GUI > method, and through > the Options GUI for hosting a local Client and Server. And a no-server Client. > For now, I've decided to just use the native Java sockets in > java.net.* and > java.nio.*. I'll push PBEM support off until the basic > architecture is more > fleshed out. My gut feeling is that real-time network play > should be the > higher priority because there are already workable PBEM solutions. > > I think that maintaining good component separation is going > to require that > we adopt Java's concept of events and listeners. We do that > to some extent > with the Observer objects, but I think it's definitely > something that we can > work on improving. I have looked hard at events and listeners before I started with Observer/Obervable, but at that time I concluded that Events wouldn't do the job for updating the UI. An Observer can register at a unique model object, whereas a Listener must register at a unique Event. This way, we would need separate (unique) events for each individual UI field, hex, stock space, etc. Say a stock price token moves from stock chart space D5 to E5. Now the Observable StockSpace ModelObject D5 sends 'token removed' to UI ViewObject D5, and E5 sends a 'token added' to its counterpart. This does not translate directly to events. If we are going to use events, I think the way to go is to replace this architecture by one in which the stock chart model as a whole, rather than the individual spaces, sends events to its UI counterpart, with the involved squares and tokens as parameters. Similarly the Map model sends events to the Map UI, and the OR model to the OR window (where we then still need to somehow identify the individual fields). |
From: Brett L. <wak...@gm...> - 2008-09-03 23:20:07
|
> -----Original Message----- > From: rai...@li... [mailto:rails-devel- > bo...@li...] On Behalf Of Erik Vos > Sent: Wednesday, September 03, 2008 2:35 PM > To: 'Development list for Rails: an 18xx game' > Subject: Re: [Rails-devel] Starting on a client/server > > > Right now, the biggest downside I can foresee is that _all_ > > clients must > > talk to the server over a transport, which means that even > > local games will > > have to load up the network bits and talk across the > > localhost. > > Not necessarily, in my opinion. I had in mind generic API's > (interfaces) at > the client and the server side, that would take any sequence of objects > at > one side and deliver them at the other side. How that is done is > internal to > the transport module, that could have several implementations. For > local > play, it is just pass-through; I don't think we need separate programs > communicating through a socket. For a client/server connection through > sockets, the objects would be serialized at one side, sent over the > socket, > and deserialized at the other side (each object must know how to > (de)serialize itself). For PBEM, we have SMTP and POP3 as transport > mechanisms (in this case the objects must be accompanied by text). Etc. > Not necessarily separate programs, but likely they'll at least be separate threads. I agree that a pass-through transport is probably the ideal way of handling this. My first transport will be network-focused, so that will need to come later. In the meantime, loopback communication is fast enough that nobody should notice the slight inefficiency. > My approach would have been first to refactor the current code to this > architecture, and then add the transport through sockets as would just > be a > new implementation of an interface. > That's not exactly how I read the function of java.net.Socket or java.nio.SocketChannel. I'd need to double-check the API docs, to be sure, but I believe what are passed are text representations of each object. So, we'll need to verify that the default toString() method is an acceptable representation for each object, or we'll need to override toString() with our own representation that does pass the necessary data. > > It's a minor > > amount of overhead, though. So other than the conceptual > > inefficiency, I > > don't think it's a major problem. The main requirement is > > that the Server > > will need two methods of startup: a command-line no-GUI > > method, and through > > the Options GUI for hosting a local Client and Server. > > And a no-server Client. > That should be handled at the UI level. The player selects "connect to a remote game", and a local server instance simply is never started. I can't really see why we'd distribute a client-only Jar package. Is there really a use-case for someone to only play remote games, and never want to play or host locally? > > For now, I've decided to just use the native Java sockets in > > java.net.* and > > java.nio.*. I'll push PBEM support off until the basic > > architecture is more > > fleshed out. My gut feeling is that real-time network play > > should be the > > higher priority because there are already workable PBEM solutions. > > > > I think that maintaining good component separation is going > > to require that > > we adopt Java's concept of events and listeners. We do that > > to some extent > > with the Observer objects, but I think it's definitely > > something that we can > > work on improving. > > I have looked hard at events and listeners before I started with > Observer/Obervable, but at that time I concluded that Events wouldn't > do the > job for updating the UI. An Observer can register at a unique model > object, > whereas a Listener must register at a unique Event. This way, we would > need > separate (unique) events for each individual UI field, hex, stock > space, > etc. > > Say a stock price token moves from stock chart space D5 to E5. Now the > Observable StockSpace ModelObject D5 sends 'token removed' to UI > ViewObject > D5, and E5 sends a 'token added' to its counterpart. This does not > translate > directly to events. > > If we are going to use events, I think the way to go is to replace this > architecture by one in which the stock chart model as a whole, rather > than > the individual spaces, sends events to its UI counterpart, with the > involved > squares and tokens as parameters. Similarly the Map model sends events > to > the Map UI, and the OR model to the OR window (where we then still need > to > somehow identify the individual fields). > I agree with you. I think the Observer/Observable model is fine for certain cases, but the Listener/Event model may be a better choice for others. There is some merit to your description where we pass stock change Events to the stock market UI as a whole, then it's the UI's job to understand how to represent that. That leaves each UI free to implement that any way they choose without the constraint of needing to process two separate actions for removing the token from one space and placing a token into a new space. I think this is something that we should come back to when I'm ready to start integrating those pieces. ---Brett. |
From: John A. T. <jat...@ja...> - 2008-09-04 00:01:44
|
On Wed, 3 Sep 2008, Brett Lentz wrote: > That's not exactly how I read the function of java.net.Socket or > java.nio.SocketChannel. > > I'd need to double-check the API docs, to be sure, but I believe what are > passed are text representations of each object. So, we'll need to verify > that the default toString() method is an acceptable representation for each > object, or we'll need to override toString() with our own representation > that does pass the necessary data. Sockets are byte channels, and you can send whatever you want across them, such as serialized objects. -- John A. Tamplin ja...@ja... 770/436-5387 HOME 4116 Manson Ave Smyrna, GA 30082-3723 |
From: Brett L. <wak...@gm...> - 2008-09-04 00:11:07
|
> -----Original Message----- > From: rai...@li... [mailto:rails-devel- > bo...@li...] On Behalf Of John A. Tamplin > Sent: Wednesday, September 03, 2008 5:02 PM > To: Development list for Rails: an 18xx game > Subject: Re: [Rails-devel] Starting on a client/server > > On Wed, 3 Sep 2008, Brett Lentz wrote: > > That's not exactly how I read the function of java.net.Socket or > > java.nio.SocketChannel. > > > > I'd need to double-check the API docs, to be sure, but I believe what > are > > passed are text representations of each object. So, we'll need to > verify > > that the default toString() method is an acceptable representation > for each > > object, or we'll need to override toString() with our own > representation > > that does pass the necessary data. > > Sockets are byte channels, and you can send whatever you want across > them, > such as serialized objects. > > -- > John A. Tamplin ja...@ja... > 770/436-5387 HOME 4116 Manson Ave > Smyrna, GA 30082-3723 > Great! So then tossing our objects over the SocketChannel ought to be relatively easy. It seems that java.nio.SocketChannel is probably a better choice than java.net.Socket. It seems like it's easier to manage multiple connections to the same port more easily with a SocketChannel. I'm new to this part of the Java API, but that's my first impression. ---Brett. |
From: brett l. <wak...@gm...> - 2008-09-04 05:10:38
|
On Wed, Sep 3, 2008 at 8:27 PM, John A. Tamplin <ja...@ja...> wrote: > Brett Lentz wrote: >> It seems that java.nio.SocketChannel is probably a better choice than >> java.net.Socket. It seems like it's easier to manage multiple connections to >> the same port more easily with a SocketChannel. I'm new to this part of the >> Java API, but that's my first impression. >> > I think the only real difference is the buffering is more efficient in > nio, but in either case I think you want a higher level API that can > encapsulate same-machine via synchronized queues, between machines with > sockets, between machines with some multicast protocol, etc. > > -- > John A. Tamplin ja...@ja... > 770/436-5387 HOME 4116 Manson Ave > Any suggestions on which API that might be? ---Brett. |
From: John A. T. <ja...@ja...> - 2008-09-04 05:14:53
|
brett lentz wrote: > Any suggestions on which API that might be? > I would decide what needs to be communicated (ie, is it going to be RPC-style [probably easier to do for web-based clients since everything has to be async there], keeping object graphs synchronized, etc) and build the API at that level, then build multiple implementations across various transports. Obviously, some of the transports are going to be better at certain styles of interaction than others, so you have to keep in mind the types of transports you want to support. -- John A. Tamplin ja...@ja... 770/436-5387 HOME 4116 Manson Ave Smyrna, GA 30082-3723 |
From: Erik V. <eri...@hc...> - 2008-09-04 19:50:32
|
> > Sockets are byte channels, and you can send whatever you want across > > them, > > such as serialized objects. > > Great! So then tossing our objects over the SocketChannel ought to be > relatively easy. You might need to think about some little protocol around that, as a byte channel has no "sentence integrity", i.e. it does not know where one message ends and another one starts. Not sure if that is really needed in this case. > It seems that java.nio.SocketChannel is probably a better choice than > java.net.Socket. It seems like it's easier to manage multiple > connections to > the same port more easily with a SocketChannel. I'm new to > this part of the > Java API, but that's my first impression. A while ago I built a kind of package around java.nio.SocketChannel for a specific case where one client controls multiple servers. I tried to make it as generic as possible. With some changes it might be turned into something that we could use. I'll check tomorrow. Erik. |
From: Brett L. <wak...@gm...> - 2008-09-04 20:21:00
|
> -----Original Message----- > From: rai...@li... [mailto:rails-devel- > bo...@li...] On Behalf Of Erik Vos > Sent: Thursday, September 04, 2008 12:51 PM > To: 'Development list for Rails: an 18xx game' > Subject: Re: [Rails-devel] Starting on a client/server > > > > Sockets are byte channels, and you can send whatever you want > across > > > them, > > > such as serialized objects. > > > > Great! So then tossing our objects over the SocketChannel ought to > be > > relatively easy. > > You might need to think about some little protocol around that, as a > byte > channel has no "sentence integrity", > i.e. it does not know where one message ends and another one starts. > Not > sure if that is really needed in this case. > We'll need to test this a bit. I suspect it shouldn't be an issue, as we'll be attaching a ByteStreamReader (or is it ByteReader, I forget) to the SocketChannel, and read until we get a whole serialized object. > > It seems that java.nio.SocketChannel is probably a better choice than > > java.net.Socket. It seems like it's easier to manage multiple > > connections to > > the same port more easily with a SocketChannel. I'm new to > > this part of the > > Java API, but that's my first impression. > > A while ago I built a kind of package around java.nio.SocketChannel for > a > specific case where one client controls multiple servers. I tried to > make it > as generic as possible. With some changes it might be turned into > something > that we could use. I'll check tomorrow. > > Erik. > That would definitely speed things up, if you've already got the basic SocketChannel implementation. ---Brett. |
From: John A. T. <ja...@ja...> - 2008-09-02 22:31:18
|
On Wed, 3 Sep 2008, Erik Vos wrote: > Anyway, I'll be happy to discuss such matters in more detail if you like, > but perhaps we can then better do that off-list, to avoid annoying the > onlookers. This is a development list, so I am not sure who would be here that you think would be annoyed by discussing a major architectural change. Even if I don't have time to help out right now, please keep it on the list. -- John A. Tamplin ja...@ja... 770/436-5387 HOME 4116 Manson Ave Smyrna, GA 30082-3723 |
From: Chris S. <chr...@gm...> - 2008-09-02 22:39:29
|
> > This is a development list, so I am not sure who would be here that you > think would be annoyed by discussing a major architectural change. Even > if I don't have time to help out right now, please keep it on the list. I agree. -- Chris Please consider the environment before printing this e-mail. |
From: John A. T. <ja...@ja...> - 2008-09-04 03:27:24
|
Brett Lentz wrote: > It seems that java.nio.SocketChannel is probably a better choice than > java.net.Socket. It seems like it's easier to manage multiple connections to > the same port more easily with a SocketChannel. I'm new to this part of the > Java API, but that's my first impression. > I think the only real difference is the buffering is more efficient in nio, but in either case I think you want a higher level API that can encapsulate same-machine via synchronized queues, between machines with sockets, between machines with some multicast protocol, etc. -- John A. Tamplin ja...@ja... 770/436-5387 HOME 4116 Manson Ave Smyrna, GA 30082-3723 |
From: brett l. <wak...@gm...> - 2008-11-02 23:12:00
|
Just a quick update... I'm still working on getting the client/server parts working. Currently, I've gotten the startup code refactored, and am just starting to tie it into the network bits. Unfortunately, the fall tends to be a busy time for me, so I haven't had as much time work on this as I'd have liked. I'm not quite ready to push this back into cvs yet. I'd like to get a bit further into having a minimally functional client/server. Being that this is an open source project, perhaps I shouldn't "go dark" for too much longer. I've been using github.com to push my changes between home and work, so that I can work in both places whenever I have a free moment. (Note: this doesn't mean we're changing revision control systems. This is just my personal place to store code. When I feel it's ready, I'll push this code back into cvs.) So, you're welcome to check the current state of things here: http://github.com/wakko666/18xx/tree/master There's some fairly major reorganization that I've done, and I've totally refactored the XML parsing. Both of these I'd like to see comments on before I push this into our code repository. Things are still in heavy flux, so none of this is set, and I really don't want to shake things up too much without make sure you guys are also happy with it. My hope is that some of these changes will help make reorganizing the game engine code a little easier. Mostly, I just wanted to update everyone that this isn't vapor, and I'm still working on it. :-) ---Brett. |
From: Erik V. <eri...@hc...> - 2008-11-03 10:41:35
|
> Just a quick update... > > I'm still working on getting the client/server parts working. > > Currently, I've gotten the startup code refactored, and am just > starting to tie it into the network bits. Unfortunately, the fall > tends to be a busy time for me, so I haven't had as much time work on > this as I'd have liked. > > I'm not quite ready to push this back into cvs yet. I'd like to get a > bit further into having a minimally functional client/server. Being > that this is an open source project, perhaps I shouldn't "go dark" for > too much longer. I've been using github.com to push my changes between > home and work, so that I can work in both places whenever I have a > free moment. (Note: this doesn't mean we're changing revision control > systems. This is just my personal place to store code. When I feel > it's ready, I'll push this code back into cvs.) Perhaps you should create a new branch in CVS for it? > So, you're welcome to check the current state of things here: > http://github.com/wakko666/18xx/tree/master I have downloaded it and tried to run client and server, but 1. The compiler reports an error in the client: The method actionPerformed(ActionEvent) of type NetworkClientWindow must override a superclass method net/sourceforge/rails/client/ui NetworkClientWindow.java line 77 1225706052046 65163 2. I can't find a Server main method. > There's some fairly major reorganization that I've done, and I've > totally refactored the XML parsing. Can you elaborate a bit on how you see XML parsing be done your way, and what the perceived benefits are? What exactly was wrong with it? It strikes me that the XMLParser API has the dreaded Document, Element and NodeList types that I have so carefully hidden inside Tag last year... Will XMLParser replace Tag, or will the former just be used by the latter? In any case, GameInfoParser isn't using Tag. Will your reorganisation extend to replacing/rewriting the configureFromXML methods of so many classes? Please be careful to retain the dynamic extensibility of the XML that we have gained by having (possibly game-specific) classes parse their own dedicated XML. > Both of these I'd like to see > comments on before I push this into our code repository. Things are > still in heavy flux, so none of this is set, and I really don't want > to shake things up too much without make sure you guys are also happy > with it. My hope is that some of these changes will help make > reorganizing the game engine code a little easier. Before I can judge all this I would like to know what your thoughts are on the direction in which the game engine need be "reorganized". What are your sore points? Of course there is much work to do in the existing code to make the client/server split possible at all, but so far I cannot see much of that in what you have published, and you seem to stir up quite a bit more than just that. In general it is not very clear to me what direction you are taking, and why, on matters that are not immediately related to the client/server split (such as XML parsing). Erik. |
From: brett l. <wak...@gm...> - 2008-11-03 19:27:10
|
On Mon, Nov 3, 2008 at 2:41 AM, Erik Vos <eri...@hc...> wrote: >> Just a quick update... >> >> I'm still working on getting the client/server parts working. >> >> Currently, I've gotten the startup code refactored, and am just >> starting to tie it into the network bits. Unfortunately, the fall >> tends to be a busy time for me, so I haven't had as much time work on >> this as I'd have liked. >> >> I'm not quite ready to push this back into cvs yet. I'd like to get a >> bit further into having a minimally functional client/server. Being >> that this is an open source project, perhaps I shouldn't "go dark" for >> too much longer. I've been using github.com to push my changes between >> home and work, so that I can work in both places whenever I have a >> free moment. (Note: this doesn't mean we're changing revision control >> systems. This is just my personal place to store code. When I feel >> it's ready, I'll push this code back into cvs.) > > Perhaps you should create a new branch in CVS for it? > Once it's in CVS, it can't be deleted. I don't want to check it into CVS only to scrap it entirely or need to completely redesign it. I'd prefer to keep our CVS tree populated with active code, rather than my random ideas. ;-) >> So, you're welcome to check the current state of things here: >> http://github.com/wakko666/18xx/tree/master > > I have downloaded it and tried to run client and server, but > 1. The compiler reports an error in the client: > The method actionPerformed(ActionEvent) of type NetworkClientWindow must > override a superclass method net/sourceforge/rails/client/ui > NetworkClientWindow.java line 77 1225706052046 65163 Hmm... I'll have to double-check that all of my changes were merged with the last push. For now, removing the @override decorator should remove the issue. > 2. I can't find a Server main method. > There is no server main method. Right now, when you hit the "new game" button, it launches both server and client (which currently don't do much of anything). I haven't yet added in the interface for starting a standalone server. I haven't quite decided what that interface will look like. I'm debating either a command-line interface, or adding a button onto the client start-up interface. >> There's some fairly major reorganization that I've done, and I've >> totally refactored the XML parsing. > > Can you elaborate a bit on how you see XML parsing be done your way, > and what the perceived benefits are? What exactly was wrong with it? > > It strikes me that the XMLParser API has the dreaded Document, Element and > NodeList > types that I have so carefully hidden inside Tag last year... > Will XMLParser replace Tag, or will the former just be used by the latter? > In any case, GameInfoParser isn't using Tag. Correct. There's nothing wrong with abstracting away the details of the XML DOM, per se. Tag does a fine job of that. I don't think our current method is doing anything wrong. Mainly, I wanted to see what it looked like to collect all of the configureFromXML methods into one single parser structure. The one benefit that this different method adds, is that we don't have to wait until we initialize a specific game object in order to parse the XML for that object. This provides access to that information to things outside of that specific game object. This will avoid similar issues like we had adding in variants and game options. At this point, I would consider this experimenting with a different method for code organization. I'm happy to scrap it to retain the existing methods if it doesn't provide any real benefits, or has some obvious problems. > Will your reorganisation extend to replacing/rewriting the configureFromXML > methods of so many classes? Please be careful to retain the > dynamic extensibility of the XML that we have gained by having > (possibly game-specific) classes parse their own dedicated XML. Yes, this was the key thing I wanted to try in a slightly different way. What I'm looking at is splitting the game classes into two parts: the game model class, and the xml parser class. The configureFromXML method would be refactored into its own class, so that the game model class is only concerned with manipulating existing java objects. As for extensibility, that hasn't changed. The only real difference is that all of the XML code is moved to their own classes, rather than living in the game classes. >> Both of these I'd like to see >> comments on before I push this into our code repository. Things are >> still in heavy flux, so none of this is set, and I really don't want >> to shake things up too much without make sure you guys are also happy >> with it. My hope is that some of these changes will help make >> reorganizing the game engine code a little easier. > > Before I can judge all this I would like to know what your thoughts are > on the direction in which the game engine need be "reorganized". > What are your sore points? > Of course there is much work to do in the existing code to make the > client/server > split possible at all, but so far I cannot see much of that in what you have > published, > and you seem to stir up quite a bit more than just that. > Well, I don't know of any specific things in the game engine that need reorganizing. I know that when we talked about this last, you mentioned that you had wanted to take a different approach on some things. Most of what I've currently done is just refactor the initialization code to allow it to start a client and a server. I've also streamlined initialization a bit. For example, there's no longer a games.properties file required to figure out what games are available. That information is loaded directly from the GamesList.xml. > In general it is not very clear to me what direction you are taking, > and why, on matters that are not immediately related to the client/server > split (such as XML parsing). > I suspected. When I started this, I just started working from the beginning of the app's initialization. There have been some things I wanted to try doing with the start-up code as I was making it aware of needing to start a client and server. I can see how it's unclear, as there's not much of the client and server bits to show off yet. it's still mostly the start-up code with some minor tweaks, a new parser, and a radically different package layout. My main concern is that I've spent a few weeks on it without showing it to anyone, and I don't think that's the right way to do an open source project. I really don't want to just dump a major code change into CVS without having some conversations about whether I'm doing things in a way that everyone is reasonably happy with. > Erik. > > ---Brett. |
From: Erik V. <eri...@hc...> - 2008-11-03 21:07:26
|
> > Perhaps you should create a new branch in CVS for it? > > > > Once it's in CVS, it can't be deleted. I don't want to check it into > CVS only to scrap it entirely or need to completely redesign it. > > I'd prefer to keep our CVS tree populated with active code, rather > than my random ideas. ;-) I'm not familiar with CVS branching, but I thought it would allow us to work on different versions in parallel, of course with the ultimate goal of merging those versions in a later stage. Never mind. > >> So, you're welcome to check the current state of things here: > >> http://github.com/wakko666/18xx/tree/master > > > > I have downloaded it and tried to run client and server, but > > 1. The compiler reports an error in the client: > > The method actionPerformed(ActionEvent) of type > NetworkClientWindow must > > override a superclass method net/sourceforge/rails/client/ui > > NetworkClientWindow.java line 77 1225706052046 65163 > > Hmm... I'll have to double-check that all of my changes were merged > with the last push. For now, removing the @override decorator should > remove the issue. > > > 2. I can't find a Server main method. > > > > There is no server main method. Right now, when you hit the "new game" > button, it launches both server and client (which currently don't do > much of anything). OK, it now works. > I haven't yet added in the interface for starting > a standalone server. I haven't quite decided what that interface will > look like. I'm debating either a command-line interface, or adding a > button onto the client start-up interface. As I'm currently always running from Eclipse, just a main() method would do. Outside an IDE you'll need some kind of a command-line interface anyway. Ultimately I would package it in two separate (executable) jars. > >> There's some fairly major reorganization that I've done, and I've > >> totally refactored the XML parsing. > > > > Can you elaborate a bit on how you see XML parsing be done your way, > > and what the perceived benefits are? What exactly was wrong with it? > > > > It strikes me that the XMLParser API has the dreaded > Document, Element and > > NodeList > > types that I have so carefully hidden inside Tag last year... > > Will XMLParser replace Tag, or will the former just be used > by the latter? > > In any case, GameInfoParser isn't using Tag. > > Correct. There's nothing wrong with abstracting away the details of > the XML DOM, per se. Tag does a fine job of that. > > I don't think our current method is doing anything wrong. Mainly, I > wanted to see what it looked like to collect all of the > configureFromXML methods into one single parser structure. > > The one benefit that this different method adds, is that we don't have > to wait until we initialize a specific game object in order to parse > the XML for that object. This provides access to that information to > things outside of that specific game object. This will avoid similar > issues like we had adding in variants and game options. The only thing is, that then in some cases the XML must be interpreted to know which game-specific XMLParser class must parse some part of it. > At this point, I would consider this experimenting with a different > method for code organization. I'm happy to scrap it to retain the > existing methods if it doesn't provide any real benefits, or has some > obvious problems. OK. I'm not too happy with the larger number of classes we will have, but I'll drop that comment if definite benefits show up. I actually see one potential benefit, although I'm not sure if you will judge it as that. Equally well, it might just be one of the goals you are aiming for. As I think I have explained before: I want to get rid of the many static methods in various classes that return non-static and game-dependent information. Bank.format() is an obvious point in case. The reason is, that when the client/server split is complete, the server should be able to accomodate multiple simultaneous games (at least potentially). These static methods are currently needed to give all kinds of object access to properties of "remote" objects: objects that are not directly related to it. Ways out of this problem include: 1. So far I have been moving towards making all these objects directly or indirectly known to GameManager, and passing along the GameManager object to all places where such access is needed. I think this is a dead end: there are too many different objects around, and putting a GameManager reference into all of them looks ugly to me. 2. We could try to make all relevant classes a subclass of one common class (call it GameObject extends Object), and putting the GameManager reference into GameObject. That would fix the problem in one fell swoop, but I'm not sure if we wouldn't run into multiple inheritance problems; this need be checked, but I think not. 3. The common GameManager reference could also be put into XMLParser, and then all objects that have an XMLParser companion would have easy access to it. But that would leave out those objects that do not parse XML, and I think we have some of these as well. Actually, option 2 looks best to me, if there are no other top classes getting in the way. To be honest, this idea only occurred to me when thinking about my previous post in this thread. > Well, I don't know of any specific things in the game engine that need > reorganizing. I know that when we talked about this last, you > mentioned that you had wanted to take a different approach on some > things. I only meant, that I would have started bottom-up by gradually loosening the ties between client and server code until we have one class where all messages would be channeled through, and then insert the communications channel there. Your approach is top-down. Perhaps we need both: yours for the framework, mine for the details, but we'll see. Erik. |
From: Brett L. <wak...@gm...> - 2008-11-03 22:46:53
|
On Mon, 2008-11-03 at 22:07 +0100, Erik Vos wrote: > > > Perhaps you should create a new branch in CVS for it? > > > > > > > Once it's in CVS, it can't be deleted. I don't want to check it into > > CVS only to scrap it entirely or need to completely redesign it. > > > > I'd prefer to keep our CVS tree populated with active code, rather > > than my random ideas. ;-) > > I'm not familiar with CVS branching, but I thought it would allow us to work > on different versions in parallel, of course with the ultimate goal of > merging those versions in a later stage. Never mind. > I think I understand what you're saying. CVS branches are supposed to be used for working in parallel. To be honest, CVS really sucks at merging. If you've never had to do it, you should consider yourself lucky. It can be a really painful process, especially if CVS randomly decides some of your files are too different, and it just marks the whole file as conflicting and leaves you to sort out exactly why. It sounds like you feel strongly that I should bring in my changes now rather than wait until they are further along. Is that about the size of it? > > >> So, you're welcome to check the current state of things here: > > >> http://github.com/wakko666/18xx/tree/master > > > > > > I have downloaded it and tried to run client and server, but > > > 1. The compiler reports an error in the client: > > > The method actionPerformed(ActionEvent) of type > > NetworkClientWindow must > > > override a superclass method net/sourceforge/rails/client/ui > > > NetworkClientWindow.java line 77 1225706052046 65163 > > > > Hmm... I'll have to double-check that all of my changes were merged > > with the last push. For now, removing the @override decorator should > > remove the issue. > > > > > 2. I can't find a Server main method. > > > > > > > There is no server main method. Right now, when you hit the "new game" > > button, it launches both server and client (which currently don't do > > much of anything). > > OK, it now works. > > > I haven't yet added in the interface for starting > > a standalone server. I haven't quite decided what that interface will > > look like. I'm debating either a command-line interface, or adding a > > button onto the client start-up interface. > > As I'm currently always running from Eclipse, just a main() method would do. > Outside an IDE you'll need some kind of a command-line interface anyway. > Ultimately I would package it in two separate (executable) jars. > > > >> There's some fairly major reorganization that I've done, and I've > > >> totally refactored the XML parsing. > > > > > > Can you elaborate a bit on how you see XML parsing be done your way, > > > and what the perceived benefits are? What exactly was wrong with it? > > > > > > It strikes me that the XMLParser API has the dreaded > > Document, Element and > > > NodeList > > > types that I have so carefully hidden inside Tag last year... > > > Will XMLParser replace Tag, or will the former just be used > > by the latter? > > > In any case, GameInfoParser isn't using Tag. > > > > Correct. There's nothing wrong with abstracting away the details of > > the XML DOM, per se. Tag does a fine job of that. > > > > I don't think our current method is doing anything wrong. Mainly, I > > wanted to see what it looked like to collect all of the > > configureFromXML methods into one single parser structure. > > > > The one benefit that this different method adds, is that we don't have > > to wait until we initialize a specific game object in order to parse > > the XML for that object. This provides access to that information to > > things outside of that specific game object. This will avoid similar > > issues like we had adding in variants and game options. > > The only thing is, that then in some cases the XML must be interpreted to > know which game-specific XMLParser class must parse some part of it. Right. On startup, the only XML that's read is the GamesList. Once we know which game is being started, we would then read that particular game's XML, and decide which game-specific parsers are needed. > > At this point, I would consider this experimenting with a different > > method for code organization. I'm happy to scrap it to retain the > > existing methods if it doesn't provide any real benefits, or has some > > obvious problems. > > OK. I'm not too happy with the larger number of classes we will have, but > I'll drop that comment if definite benefits show up. > > > I actually see one potential benefit, although I'm not sure if you will > judge it as that. Equally well, it might just be one of the goals you are > aiming for. > > As I think I have explained before: I want to get rid of the many static > methods in various classes that return non-static and game-dependent > information. Bank.format() is an obvious point in case. The reason is, that > when the client/server split is complete, the server should be able to > accomodate multiple simultaneous games (at least potentially). > I agree with you. Static should be used sparingly, and only when absolutely necessary. > These static methods are currently needed to give all kinds of object access > to properties of "remote" objects: objects that are not directly related to > it. Ways out of this problem include: > > 1. So far I have been moving towards making all these objects directly or > indirectly known to GameManager, and passing along the GameManager object to > all places where such access is needed. I think this is a dead end: there > are too many different objects around, and putting a GameManager reference > into all of them looks ugly to me. > Agreed. > 2. We could try to make all relevant classes a subclass of one common class > (call it GameObject extends Object), and putting the GameManager reference > into GameObject. That would fix the problem in one fell swoop, but I'm not > sure if we wouldn't run into multiple inheritance problems; this need be > checked, but I think not. > > 3. The common GameManager reference could also be put into XMLParser, and > then all objects that have an XMLParser companion would have easy access to > it. But that would leave out those objects that do not parse XML, and I > think we have some of these as well. > > Actually, option 2 looks best to me, if there are no other top classes > getting in the way. To be honest, this idea only occurred to me when > thinking about my previous post in this thread. > I'm not sure I like any of these as individual solutions. I can't quite express the problems I see with those solutions in a way that I'm happy with. I've spent the last 30 minutes trying to type it out, but none of it sounds right. In general, I'd like to improve the accessor methods so that we don't require GameManager to know or do as much. For example, in Tile there's the isLayableNow() method: public boolean isLayableNow() { return GameManager.getInstance().getCurrentPhase().isTileColourAllowed(colourName); } This method is currently used exactly once in our entire codebase. This method is used in OperatingRound. In my mind, there are two problems with this. 1. Why do we need a whole new method in Tile for information that Tile doesn't even have? 2. I think that this is information that Tile *should* have. Tile shouldn't need to call all the way up to the GameManager to figure this out. One likely answer is to change isLayableNow()'s signature to be 'isLayableNow(phaseNumber)' or something similar. That way Tile has the information it needs to be authoritative for this information, rather than relying on GameManager to know this. My view is that Tile should be constructed with enough information to know these sorts of things on its own. If it needs GameManager, it's because we aren't passing in enough information to the Tile objects at construction time. To fix our overuse of static methods, I think we need to improve the accessor methods and how we're constructing our objects. When we no longer require instances of GameManager everywhere, then we no longer require GameManager to have the static getInstance() method. I believe the same logic applies to most of the other static methods we have. I hope that makes sense. > > Well, I don't know of any specific things in the game engine that need > > reorganizing. I know that when we talked about this last, you > > mentioned that you had wanted to take a different approach on some > > things. > > I only meant, that I would have started bottom-up by gradually loosening the > ties between client and server code until we have one class where all > messages would be channeled through, and then insert the communications > channel there. Your approach is top-down. Perhaps we need both: yours for > the framework, mine for the details, but we'll see. > I agree, I think we need both approaches. For the last year or so, you've been slowly improving the existing code to better support client/server behavior. I've just started on the other end of it. ;-) I think what's important is that perhaps I'm wrong about wanting to wait to commit this. Perhaps what I've got so far *is* ready for a wider audience and really should be committed into CVS. I was beginning to second-guess myself about wanting to wait longer before I committed it to the project. So, this thread was intended to get your opinions about it. I figure, if I'm not sure I'm doing it right, I should run it by someone else. :-) > Erik. > ---Brett. May all your PUSHes be POPped. |
From: Erik V. <eri...@hc...> - 2008-11-04 20:46:37
|
> It sounds like you feel strongly that I should bring in my changes now > rather than wait until they are further along. Is that about > the size of > it? No, that is not what I meant to say. My intention was to emphasize that, once you are going to check it in, that during the integration period it could better be kept separate in some way or other from the existing code, until we agree that the integration is going to be successful. But I don't know what your plan is - first doing an (almost) full integration separately? The point is, that I suspect that not that many classes will escape from being affected by your new approach. (snipped a lot) > In general, I'd like to improve the accessor methods so that we don't > require GameManager to know or do as much. > > For example, in Tile there's the isLayableNow() method: > > public boolean isLayableNow() { > return > GameManager.getInstance().getCurrentPhase().isTileColourAllowe > d(colourName); > } Good example. > This method is currently used exactly once in our entire > codebase. This > method is used in OperatingRound. > > In my mind, there are two problems with this. > > 1. Why do we need a whole new method in Tile for information that Tile > doesn't even have? Fully agree. This logic should be moved to OperatingRound (which BTW already has a GameManager reference). > 2. I think that this is information that Tile *should* have. Tile > shouldn't need to call all the way up to the GameManager to > figure this > out. Fully disagree. Tiles should mind their own business, which is how they look like. Even the fact that they know where they are laid is somewhat suspicious; in fact this knowledge is only used to calculate the number of available tiles; so that ArrayList<MapHex> could as well be replaced by a number. > One likely answer is to change isLayableNow()'s signature to be > 'isLayableNow(phaseNumber)' or something similar. That way > Tile has the > information it needs to be authoritative for this information, rather > than relying on GameManager to know this. As will be clear now, my solution is to replace tile.isLayableNow() (in OperatingRound) by currentPhase.isTileColourAllowed(tile.getColourName()). Then we can remove this whole silly and redundant method (of my own making, I'm afraid). > My view is that Tile should be constructed with enough information to > know these sorts of things on its own. If it needs GameManager, it's > because we aren't passing in enough information to the Tile objects at > construction time. > > To fix our overuse of static methods, I think we need to improve the > accessor methods and how we're constructing our objects. > > When we no longer require instances of GameManager everywhere, then we > no longer require GameManager to have the static > getInstance() method. > > I believe the same logic applies to most of the other static > methods we > have. > > I hope that makes sense. It sure makes, but I would phrase the solution as making a better distinction between game logic (I had almost written: business logic) and static objects. Tiles, companies, shares, trains are mainly static objects (although most of these must know their owners). The game logic should be in (or moved to) the Round instances and some related classes. That is why I find your example so instructive. But not all cases will not be so easy to fix, I'm afraid. > I think what's important is that perhaps I'm wrong about > wanting to wait > to commit this. Perhaps what I've got so far *is* ready for a wider > audience and really should be committed into CVS. I was beginning to > second-guess myself about wanting to wait longer before I committed it > to the project. So, this thread was intended to get your > opinions about > it. I figure, if I'm not sure I'm doing it right, I should run it by > someone else. :-) Committing is OK with me, but please do it in a way that all the old code keeps running until your new code is sufficiently well-integrated to show its superiority.... Erik. |
From: Brett L. <wak...@gm...> - 2008-11-04 21:48:04
|
On Tue, 2008-11-04 at 21:46 +0100, Erik Vos wrote: > > It sounds like you feel strongly that I should bring in my changes now > > rather than wait until they are further along. Is that about > > the size of > > it? > > No, that is not what I meant to say. My intention was to emphasize that, > once you are going to check it in, that during the integration period it > could better be kept separate in some way or other from the existing code, > until we agree that the integration is going to be successful. But I don't > know what your plan is - first doing an (almost) full integration > separately? > The point is, that I suspect that not that many classes will escape from > being affected by your new approach. > Agreed. I had assumed that I'd just create a new CVS module, or check it into sourceforge's SVN service if we wanted to change over to subversion (not trying to start that discussion now, just mentioning it because it's an available option). > (snipped a lot) > > > In general, I'd like to improve the accessor methods so that we don't > > require GameManager to know or do as much. > > > > For example, in Tile there's the isLayableNow() method: > > > > public boolean isLayableNow() { > > return > > GameManager.getInstance().getCurrentPhase().isTileColourAllowe > > d(colourName); > > } > > Good example. > > > This method is currently used exactly once in our entire > > codebase. This > > method is used in OperatingRound. > > > > In my mind, there are two problems with this. > > > > 1. Why do we need a whole new method in Tile for information that Tile > > doesn't even have? > > Fully agree. This logic should be moved to OperatingRound (which BTW already > has a GameManager reference). > > > 2. I think that this is information that Tile *should* have. Tile > > shouldn't need to call all the way up to the GameManager to > > figure this > > out. > > Fully disagree. Tiles should mind their own business, which is how they look > like. > Even the fact that they know where they are laid is somewhat suspicious; in > fact this knowledge is only used to calculate the number of available tiles; > so that ArrayList<MapHex> could as well be replaced by a number. > Fair enough. I think we agree on the important point, which is that we need to have a clear purpose for each class, and refactor anything that has been added that doesn't line up with that purpose. > > One likely answer is to change isLayableNow()'s signature to be > > 'isLayableNow(phaseNumber)' or something similar. That way > > Tile has the > > information it needs to be authoritative for this information, rather > > than relying on GameManager to know this. > > As will be clear now, my solution is to replace tile.isLayableNow() (in > OperatingRound) by currentPhase.isTileColourAllowed(tile.getColourName()). > Then we can remove this whole silly and redundant method > (of my own making, I'm afraid). > > > My view is that Tile should be constructed with enough information to > > know these sorts of things on its own. If it needs GameManager, it's > > because we aren't passing in enough information to the Tile objects at > > construction time. > > > > To fix our overuse of static methods, I think we need to improve the > > accessor methods and how we're constructing our objects. > > > > When we no longer require instances of GameManager everywhere, then we > > no longer require GameManager to have the static > > getInstance() method. > > > > I believe the same logic applies to most of the other static > > methods we > > have. > > > > I hope that makes sense. > > It sure makes, but I would phrase the solution as making a better > distinction between game logic (I had almost written: business logic) and > static objects. Tiles, companies, shares, trains are mainly static objects > (although most of these must know their owners). The game logic should be in > (or moved to) the Round instances and some related classes. That is why I > find your example so instructive. > > But not all cases will not be so easy to fix, I'm afraid. > Of course, not everything is a one-line method. I picked an obvious example to help illustrate my idea. ;-) I think we agree on the basic concept. We need a series of objects that hold the game state, and a series of objects that operate upon that state, and we need to clearly define which is which. > > > I think what's important is that perhaps I'm wrong about > > wanting to wait > > to commit this. Perhaps what I've got so far *is* ready for a wider > > audience and really should be committed into CVS. I was beginning to > > second-guess myself about wanting to wait longer before I committed it > > to the project. So, this thread was intended to get your > > opinions about > > it. I figure, if I'm not sure I'm doing it right, I should run it by > > someone else. :-) > > Committing is OK with me, but please do it in a way that all the old code > keeps running until your new code is sufficiently well-integrated to show > its superiority.... > > Erik. Alright. I think, for now, I'll just keep it in my git tree. I want to integrate the client/server bits a little more so that when it's committed, it'll be a stable base for integrating the rest of the existing code. ---Brett. Experience, n.: Something you don't get until just after you need it. -- Olivier |
From: Mark S. <mar...@gm...> - 2008-11-05 00:42:55
|
I would like to pose a question using your example routine in the Tile Class: 325 /** 326 * Is the tile layable now (in the current phase)? 327 * 328 * @return 329 */ 330 public boolean isLayableNow() { 331 return GameManager.getInstance().getCurrentPhase().isTileColourAllowed(colourName); 332 } This calls in the Game Manager the 'getInstance ()' routine: 336 /** 337 * @return instance of GameManager 338 */ 339 public static GameManager getInstance() { 340 return instance; 341 } What I am very puzzled by is why bother to call to get the instance at all? If you have the GameManager, you already have a copy of the instance. You can reduce the original call to: 325 /** 326 * Is the tile layable now (in the current phase)? 327 * 328 * @return 329 */ 330 public boolean isLayableNow() { 331 return GameManager.getCurrentPhase().isTileColourAllowed(colourName); 332 } And even saving the a pointer to the object within the object is a circular reference that accomplishes nothing useful that I can see. Maybe I am failing to realize why you bother with this self-referencing object. Mark |
From: Erik V. <eri...@hc...> - 2008-11-05 20:59:24
|
Mark, I'm not sure if I understand your point. In GameManager, getInstance() is a static method, but getCurrentPhase() is not. Your shortened call wouldn't compile. Generally spoken, there might indeed be a lot of unwieldy code around. The code base has grown in ways that may have caused inconsistencies and redundant code (we have just seen an example - I'm going to fix it soon), unused or almost duplicate methods etc. When I find such a case, I often try to fix it, but not always is the solution immediately clear and other priorities may cause it being forgotten. So it goes. Over time all will be done (I hope). Erik. > -----Original Message----- > From: Mark Smith [mailto:mar...@gm...] > Sent: Wednesday 05 November 2008 01:43 > To: Development list for Rails: an 18xx game > Subject: Re: [Rails-devel] Starting on a client/server > > I would like to pose a question using your example routine in > the Tile Class: > > 325 /** > 326 * Is the tile layable now (in the current phase)? > 327 * > 328 * @return > 329 */ > 330 public boolean isLayableNow() { > 331 return > GameManager.getInstance().getCurrentPhase().isTileColourAllowe > d(colourName); > 332 } > > This calls in the Game Manager the 'getInstance ()' routine: > > 336 /** > 337 * @return instance of GameManager > 338 */ > 339 public static GameManager getInstance() { > 340 return instance; > 341 } > > What I am very puzzled by is why bother to call to get the > instance at all? > If you have the GameManager, you already have a copy of the instance. > You can reduce the original call to: > > 325 /** > 326 * Is the tile layable now (in the current phase)? > 327 * > 328 * @return > 329 */ > 330 public boolean isLayableNow() { > 331 return > GameManager.getCurrentPhase().isTileColourAllowed(colourName); > 332 } > > And even saving the a pointer to the object within the object is a > circular reference that accomplishes nothing useful that I can see. > > Maybe I am failing to realize why you bother with this > self-referencing object. > > Mark > > -------------------------------------------------------------- > ----------- > This SF.Net email is sponsored by the Moblin Your Move > Developer's challenge > Build the coolest Linux based applications with Moblin SDK & > win great prizes > Grand prize is a trip for two to an Open Source event > anywhere in the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel > |
From: Mark S. <mar...@gm...> - 2008-11-06 00:10:48
|
Hmm... I believe I understand now why my "code-reduction" would not work. I have seen cases where you store the instance of an object within the object as a static variable, and have a static method to return the instance. I generally avoid writing code that depends on global variables, and this is one example. If I need a variable down in a routine, I attempt to pass it in so there is no ambiguity. For this example I would have the routine that calls 'isLayableNow' to instead get the tile colour from the Tile Class, then have the Phase Class be called asking 'isTileColorAllowed' instead. You might still have a similar problem of finding the current phase by whatever routine is currently calling 'isLayableNow' but it would need to be examined. Searching for the use of this routine I find one use in 'OperatingRound' class, LayTile routine. And it seems to be just a double-check that it did not get selected by mistake, only an error message is produced if it is true. Mark On Wed, Nov 5, 2008 at 3:59 PM, Erik Vos <eri...@hc...> wrote: > Mark, > > I'm not sure if I understand your point. > In GameManager, getInstance() is a static method, but getCurrentPhase() is > not. > Your shortened call wouldn't compile. > > Generally spoken, there might indeed be a lot of unwieldy code around. > The code base has grown in ways that may have caused inconsistencies and > redundant code (we have just seen an example - I'm going to fix it soon), > unused or almost duplicate methods etc. When I find such a case, I often try > to fix it, but not always is the solution immediately clear and other > priorities may cause it being forgotten. So it goes. Over time all will be > done (I hope). > > Erik. > > >> -----Original Message----- >> From: Mark Smith [mailto:mar...@gm...] >> Sent: Wednesday 05 November 2008 01:43 >> To: Development list for Rails: an 18xx game >> Subject: Re: [Rails-devel] Starting on a client/server >> >> I would like to pose a question using your example routine in >> the Tile Class: >> >> 325 /** >> 326 * Is the tile layable now (in the current phase)? >> 327 * >> 328 * @return >> 329 */ >> 330 public boolean isLayableNow() { >> 331 return >> GameManager.getInstance().getCurrentPhase().isTileColourAllowe >> d(colourName); >> 332 } >> >> This calls in the Game Manager the 'getInstance ()' routine: >> >> 336 /** >> 337 * @return instance of GameManager >> 338 */ >> 339 public static GameManager getInstance() { >> 340 return instance; >> 341 } >> >> What I am very puzzled by is why bother to call to get the >> instance at all? >> If you have the GameManager, you already have a copy of the instance. >> You can reduce the original call to: >> >> 325 /** >> 326 * Is the tile layable now (in the current phase)? >> 327 * >> 328 * @return >> 329 */ >> 330 public boolean isLayableNow() { >> 331 return >> GameManager.getCurrentPhase().isTileColourAllowed(colourName); >> 332 } >> >> And even saving the a pointer to the object within the object is a >> circular reference that accomplishes nothing useful that I can see. >> >> Maybe I am failing to realize why you bother with this >> self-referencing object. >> >> Mark >> >> -------------------------------------------------------------- >> ----------- >> This SF.Net email is sponsored by the Moblin Your Move >> Developer's challenge >> Build the coolest Linux based applications with Moblin SDK & >> win great prizes >> Grand prize is a trip for two to an Open Source event >> anywhere in the world >> http://moblin-contest.org/redirect.php?banner_id=100&url=/ >> _______________________________________________ >> Rails-devel mailing list >> Rai...@li... >> https://lists.sourceforge.net/lists/listinfo/rails-devel >> > > > ------------------------------------------------------------------------- > This SF.Net email is sponsored by the Moblin Your Move Developer's challenge > Build the coolest Linux based applications with Moblin SDK & win great prizes > Grand prize is a trip for two to an Open Source event anywhere in the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel > |
From: Mark S. <mar...@gm...> - 2008-11-06 01:15:49
|
If this makes sense... then OperatingRound.java class, layTile routine could be changed from: 323 if (!tile.isLayableNow()) { 324 errMsg = 325 LocalText.getText("TileNotYetAvailable", 326 tile.getExternalId()); 327 break; 328 } to 323 if (!gameManager.getCurrentPhase().isTileColourAllowed (tile.getColourName())) { 324 errMsg = 325 LocalText.getText("TileNotYetAvailable", 326 tile.getExternalId()); 327 break; 328 } This would allow the isLayableNow routine to be tossed... and have the Operating Round which knows about the gameManager to perform the check. I have applied this change to my copy of the code, it compiles without error. And I then tossed the isLayableNow routine out, and the abstract reference in Tile as well. Mark On Wed, Nov 5, 2008 at 7:10 PM, Mark Smith <mar...@gm...> wrote: > Hmm... I believe I understand now why my "code-reduction" would not > work. I have seen cases where you store the instance of an object > within the object as a static variable, and have a static method to > return the instance. I generally avoid writing code that depends on > global variables, and this is one example. If I need a variable down > in a routine, I attempt to pass it in so there is no ambiguity. > > For this example I would have the routine that calls 'isLayableNow' to > instead get the tile colour from the Tile Class, then have the Phase > Class be called asking 'isTileColorAllowed' instead. > > You might still have a similar problem of finding the current phase by > whatever routine is currently calling 'isLayableNow' but it would need > to be examined. Searching for the use of this routine I find one use > in 'OperatingRound' class, LayTile routine. And it seems to be just a > double-check that it did not get selected by mistake, only an error > message is produced if it is true. > > Mark > |