On Fri, May 03, 2013 at 02:45:01PM -0500, Dick Hollenbeck wrote: > If they are not in one class, this makes the mix-in tougher back up at the > PCB_BASE_FRAME. > You end up with 2,3,4 classes, each holding a BOARD*, and each being mixed in > via multiple > inheritance? Instead of one class.
I also said I didn't like the forceful mixin, in fact. I better see the board actions as a separate functions rather than a class. > I am thinking that multiple inheritance at the FRAME level is one line of > code to do the > mixin. And yes, of course it can live detached as well. One class, two > living > environments. If instantiated stand alone, then it is an interface for > python. If > instantiated as part of frame, it augments a frame. Why do you need to *instantiate* procedural code? Passing boards around is easier, especially since the plan is to have many boards in the same core IIRC. Also that would have a *huge* interface, not exactly easy to maintain. > Since it is ONLY actions, i.e. procedural calls, then the integration happens > in the > frame, no that is already done. Just move *procedural* functions into > BOARD_ACTIONS, no > event handling, no dialogs, no UI. So no needed data members. In fact no class, only procedural code. Object = data with operation on it. These are only operations on data somewhere else, so no object (no polymorphism needed either). A namespace if you want. Exception: long (i.e. many calls needed actions) would need a support class to keep the state. Example 1: case for moving a track (only to give an idea, of course); let's say that for some reason you can't simply do a TRACK::SetPosition (everything invented!), so you need support from the board or whatever. Or maybe it should only succeed depending on some DRC check, I don't know. Simple interface function: BA_MoveTrack and parameters (board, track whatever). Nothing to instantiate, just call it. Putting it as a mixin would only gain omission of the board pointer. If calling from the frame it would be BA_MoveTrack( GetBoard(), stuff ) instead of BA_MoveTrack( stuff ). Too marginal for a so big mixin. >From the outside it would be BA_MoveTrack( GetBoard(), stuff ) (GetBoard() obviously could be a local or member variable). Otherwise you would have to a) allocate a whole object for BA (passing the board) and b) calling each single action from that object. So: ba = new BoardAction(GetBoard()); ba.MoveTrack(stuff); instead of BA_MoveTrack(GetBoard(), stuff); what do you gain interposing a class? Example 2: the plot controller. It has state between calls so it need members to remember it. Instantiate a controller, set options, plot, close delete controller. Want to do *two* plots in parallel? No problem, instantiate two of them, it should work. It's not an object in it's 'purest' sense but we don't have closures, so it will have to do. Even the example 1 could be 'forced' to work as a class (but why?) if you really wanted. BA_TrackMover trackmover( GetBoard() ); trackmover.do(stuff); That's exactly a command pattern. Runtime cost is nearly zero if on the stack (since it only keeps a board). But why should I create a class when a function suffice? > What am I missing? That board actions don't need state in most of the cases and that it don't need to be mixed in to the frame (PCB_FRAME IS-A BOARD_ACTIONS? I don't think so...). And, in fact, even without the mixin you already have access to the board. > The dialogs can stuff something like the PLUGIN PROPERTIES object, which > could be renamed > to say, OPTIONS. Then OPTIONS can be passed to some of the functions in > BOARD_ACTIONS. > Or python can stuff OPTIONS, and do the same. Right. In the dialog (let's say "save as") do something like: OPTIONS opt; // Stuffed with stuff BA_SaveAs( GetBoard(), &opt ); >From scripting no differences. This GetBoard would go to the frame or access some member in the dialog, it doesn't matter. Otherwise, using a pseudo command pattern: OPTIONS opt; // Stuffed with stuff BA_BoardSaver saver( GetBoard() ); saver.SaveAs(&opt) That's not exactly a command pattern: these 'command classes' would have related function. The BA_BoardSaver could have Save and SaveAs, for example. A true command pattern would be more like this: OPTIONS opt; BA_BoardSaveAsCmd saver( GetBoard() ); saver.SetOptions(&opt); saver.execute(); // This would be polymorphic across commands However, one class for each command is a PITA and it's not warranted if you don't need the features of command (like serializable undo). As I said you don't need a class for these things. > This has been my vision for 2 years. Just saying you don't like it or that > it is not > necessary, is actually an insufficient argument. Will it work, and what is > better if > anything, and why? Yes it would work. My argument is: does it need to be a) a huge class and b) a class at all when since it's mostly procedural code there is no state to maintain? the only advantage I see in a mixin is not having to pass the board to calls. Disadvantages are: the huge interface gives huge recompilations; you can't keep separate 'transactions' in parallel, it the cases where there actually is state to be kept; the state for *all* the operations is put in one big class (so the BOARD_ACTIONS class would have the state for plotting, near the state for drilling, near the state for whatever and every else operation needs state). In short it becomes almost a parallel global namespace (or more like a big union, since you will not use every state as the same time). I'd say it's almost the opposite of modular programming. I discovered there is even a name for that: the blob :D http://www.cs.iastate.edu/~hridesh/teaching/362/07/01/notes/antipatterns.pdf >From slide 16. And since it's an OO design class the idea 'just use functions' is not contemplated (in Java you couldn't do it anyway) Here is explained better: http://sourcemaking.com/antipatterns/the-blob I'm am not against OO (not always, at least) but I think than functional and procedural have their use. With my idea you have: no classes when states is not needed, the function/operation classes can be light and divided between files without problem (so faster recompilation), every 'group' of operation with state has its own little state (and it's independant with other operations and even other instances of the same operation). You have to pass the board at each call, but for these advantages I think is acceptable (also: it would be needed anyway for between-board operations). Of course the 'best' solution would be finding the right home for each operation, if possible (asking the track to move itself, for example: but it would have to find it's own board and so on, it's not trivial) These are the reason for which I think it would work better. Have I forgot something? -- Lorenzo Marcantonio Logos Srl _______________________________________________ Mailing list: https://launchpad.net/~kicad-developers Post to : [email protected] Unsubscribe : https://launchpad.net/~kicad-developers More help : https://help.launchpad.net/ListHelp

