From: Stefan F. <ste...@we...> - 2011-08-12 20:15:18
|
Erik: just a comment on your thoughts and a short summary of my current plans: I understand that the issue how various classes can interact with each other has to be solved and needs consideration. However the solution to put everything very close together is similar to solve such problems by making all variables global. I am currently sketching/designing a proposal/possibility to break up the round classes and still allowing classes to interact in a disciplined way: My solution will be to store such information in an abstraction called context, which allows to store objects that implement a contextItem interface. That includes for example information about the current phase, the active player, the operating company, the available colors etc. I will split the round classes into two separate parts: First a replacement for the round mechanism, that defines the progression between players (for share rounds) or companies (for operating rounds). And then the sub-phases inside a round will all get separate classes called activities. So there will be a LayTileActivity, a LayTokenActivity, a BuyTrainActivity etc. for the OperatingRound. They provide and execute actions similar to the Correction managers. All of this should be configurable using a Round.xml file, which will allow to define not only the activities used, but also the sequence of those. For this all activities will get a slot that allows to assign ActivationStrategies to decouple the activity (especially for those activities that only occur after specific events etc.) Finally the RoundManager asks the current active Round which Activities are there, checks if they are active currently by calling their ActivationStrategies, allows the Round classes to add additional information to the current context which is then passed to the active Activities. Based on the context the activities create the actions. The RoundManager collects the actions and forwards them to the UI. Given the selected action the RoundManager then returns it to the according Activity class object. I will hope to come up with a prototype implementation of the new framework soon, as working code is usually more convincing than lots of words. Stefan On Friday, August 12, 2011 05:21:25 pm Erik Vos wrote: > Hi Stefan, > > I agree with 100% of what you are saying, but there is one implicit > presumption: that we can avoid side effects. And that isn't generally > true. > > Take your alternative proposal to handle phase actions (or triggers - I > don't like that word either, but that aside). > Now the Phase tries to reach the action taker by calling a stub, that call > is passed on and must in some Round subclass be implemented with actual > code. > You propose a register-and-call-back approach, which is fine, if only the > action taker can access the registration point. Getting access is the > central problem; read on. > > There is quite some history before I arrived at the current architecture. > Originally I tried to follow the let-each-object-mind-its-own-business > approach (following the original OO paradigm), which led to a situation > where many different objects (portfolios, public companies etc.) were > executing various parts of particular action types. > This worked in simple cases, but as more features got implemented, more > side-effects cropped up, where code in various objects needed to call > methods in different, sometimes remote objects. So the question arose how > an object can get access to another object to which it doesn't have a > direct reference. > > Initially this was often done via static methods calls. But I had to > abandon that approach as I realised that it would inhibit foreseen future > developments. > > Mainly in the last two years I found myself following two paths: > 1. Move code out of the objects into the Round classes, which have easier > access to other objects via the GameManager. You will not believe it, but > in my perception these moves have much simplified and clarified the > affected code parts. > 2. Pass down references to the various managers (including GameManager), > usually via the ubiquitous finishConfiguration methods, which are > specifically intended to create any required relationships after all XML > has been parsed. > > There transitions aren't complete, but now that we have most OR code in the > OR class, it has become much easier to add new or override existing > behaviour. And about every object is now reachable from there. > > The situation has become much more complex with the advent of > rounds-within-rounds in 1856, 1835 and 18EU. In 1835, Prussian formation > rounds even run inside company turns. It took a while before I had arrived > at a workable approach to make this happen. > > Now I'm facing your proposal to fragment the OR class into an untold number > of separate classes. Your example of the correction classes is > instructive, and I regret that I have not looked at and learned from your > code in an earlier stage. But correction is a very simple case, out of the > game as it were, with just one item being affected without side effects. > Fine. But I'm far from convinced that it will look equally nice if we are > going to apply this concept to real game actions, with all required side > effects, and that it really will simplify rather than even more complicate > the code. > > You certainly have set my thoughts in motion, and I'm open to be convinced > by more realistic examples. But I hope you'll understand that I have no > great desire to set myself to start reworking these central concepts once > again. > > Erik. > > > -----Original Message----- > > From: Stefan Frey [mailto:ste...@we...] > > Sent: Thursday, August 11, 2011 10:38 PM > > To: Development list for Rails: an 18xx game > > Subject: Re: [Rails-devel] Current implementation, branch Rails 2.0? > > > > > All fine, but so what? Is size bad per se? > > > > Erik, > > No certainly not. All this is not about good or bad. In one sense the > > size shows the thoughts and efforts for all details you have put into > > those > > classes. > > > It is the other way around: As I do not have the time and the memory to > > understand all thoughts and conditions you considered, that created that > > code, I would prefer to digest all that in little portions. > > > > Organizing code into classes allows to review only the relevant classes > > that > > > you need know. It is like organizing stuff into little boxes where you > > put labels on the boxes what is inside. This makes it much easier to > > find > > things > > > and to understand the big picture: Maybe like in a big department store: > It is > > > much easier to get an overview by studying the directory of the store > > instead > > > of searching every shelf. > > > > An object orientated languages allows storing pieces of code in classes > > and if > > > I want rewrite/change/add something to a class, I have to make sure that > > after my changes everything works as before. If the class is small, it is > > easier > > > to check if I do not introduce side effects and I only have to test the > > part > > > where the class is responsible for: So take the example for the > > OperatingRound. If I change anything inside I have to test all > > functionality > > > which is managed by the OperatingRound. Thus I change something related > > to token lay, it can potentially have side effects on tile laying, > > revenue payouts, train buying, loans etc. > > > > If the token lay code is inside in a separate class it is impossible to > > effect the > > > other functionality of OperatingRound. > > > > I had the issue more than a year ago: I started adding the NoMap > > functionalities which in principle should only change Tile and Token Lay. > > However due to side effects of my (at that time bad understanding) of the > > step mechanism inside the OperatingRound I broke the 1856 loan > > mechanism. > > And I was not even aware of that code as this code was part of a subclass > > of > > > OperatingRound. > > > > The same issue about the size of classes effects writing unit tests: For > > refactoring the best is to have the class covered fully by unit tests. If > > you > > > have two small classes instead of one large you can start refactoring > > earlier > > > than you had to write all tests first. > > > > And the other good thing is, that with smaller classes it is less likely > > that two > > > people work at the same time on the same class, thus it makes merging and > > potential merge conflicts less likely. > > > > For my daily job I have to deal with large programs in non-object > > orientated > > > languages and even there I prefer to split problems into smaller, > > independent pieces. Especially if you come back to those programs several > > years later, it makes it much easier to enhance or fix something. > > > > OK enough text, but it is not about fashionable or good/bad, it is simply > > about making coding easier and so increase the fun part of it. > > > > Stefan > > > > ´ > > --------------------------------------------------------------------------- > - -- > > > Get a FREE DOWNLOAD! and learn more about uberSVN rich system, user > > administration capabilities and model configuration. Take the hassle out > > of > > > deploying and managing Subversion and the tools developers use with it. > > http://p.sf.net/sfu/wandisco-dev2dev > > _______________________________________________ > > Rails-devel mailing list > > Rai...@li... > > https://lists.sourceforge.net/lists/listinfo/rails-devel > > --------------------------------------------------------------------------- > --- FREE DOWNLOAD - uberSVN with Social Coding for Subversion. > Subversion made easy with a complete admin console. Easy > to use, easy to manage, easy to install, easy to extend. > Get a Free download of the new open ALM Subversion platform now. > http://p.sf.net/sfu/wandisco-dev2dev > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |