6 ms·
“But first of all, the OO inheritance here is irrelevant. The queen is the only piece which actually “inherits” properties from other pieces! We don't need an o
by valuearb 9y ago
“But first of all, the OO inheritance here is irrelevant. The queen is the only piece which actually “inherits” properties from other pieces! We don't need an object model to simply reuse some functions to calculate legal moves given a position. Just a few global functions.”
Don’t all pieces have a location? Aren’t all pieces movable? Might we want to display pieces? Do we want to journal them to files to save game state, or their moves to streams to play remotely?
All of these things can be done procedurally, but they also fit nicely into an OO design.
- fjdfhdjldj 9y agobut then why use OO? what does OO offer that this method does not? In fact one could argue that this method offers better decoupling since it separates the rendering from the game Data.
- valuearb 9y agoYou use OO because your interviewer wants an example that demonstrates you understand it. Secondly, OO is more easily extensible. If the company wants the game to support other size boards, bit wise storage has to be ripped out. 90% of the work in 90% of the jobs is writing clear, easily maintainable and extensible code, not maximizing performance. Frankly, if I interview someone who answers a question like OP, i pass thinking their code will be a premature optimization nightmares.
- christophilus 9y agoExcept, this is not premature optimization. Chess programs are a domain the author is familiar with. He goes out of his way to explain why-- based on his experience-- chess code should be written with space-optimization in mind. Secondly, if you want to support non-standard boards, his solution requires a small tweak (depending on the language): long -> bigint and some parameter to denote board size.
- valuearb 9y agoYea, you are describing code that’s more difficult to enhance and maintain. Your pieces and board objects can have serialize/deserialize methods that write/read them to/from bitboards for most efficient storage for whatever variant of chess you want, while still having your code in an OO design that’s easier to understand and extend. And allow you to demonstrate the skills the gdmn interviewer wanted you to demonstrate, which is the actual point of the excercise!
- loup-vaillant 9y agoI'd rather fail the interview than work for the one who failed me in this case. Assuming I am asked to design something in a domain I am familiar with, where an OOP-looking solution is not a good approach, I will simply go with a good approach instead. If this triggers a discussion, wonderful. If the interviewer assumes I don't understand OOP, shame on them for not explicitly asking for an OOP design in the first place. And if the interviewer suggests I should go for an OOP design instead of my solution, I will contradict them on the spot —politely. I may comply for the sake of the exercise, but will repeat and insist that there are better approaches to this class of problems —politely. More generally, I am highly sceptical of claims that OO designs are in general easier to understand, maintain, and extend (this includes this chess example, where I believe the bit-board approach is competitive even for variable board sizes). They're often not, if only because being OO for the sake of it tends to generate more code. More code to understand, more code to debug, more code to extend… you get the idea. I also tend to believe OOP is not the best approach for most problem domains, possibly even including GUI (I have yet to study this in detail). I'd rather not work for shops that insist on using OOP everywhere.
- loup-vaillant 9y agoOO is better because bundling data and code together is better, because code is data, and I have no idea what I'm babbling about. </strawman> The real advantage of OOP, as used today in Java/C++, is instantiation. Instead of having procedures working on global variables, you have procedure working on local variables, including complex data structures. Instantiation took some time to get widespread adoption. Originally, even local variables were actually global, scoped variables, thus forbidding even recursive calls (see earlier versions of FORTRAN). Programming languages since use a stack to instantiate their local variables (and return pointers), thus enabling recursion. The instantiation of more complex data structures (arrays, user defined structs…) followed. Ironically, instantiation took some time to become ubiquitous in the C language even though it fully supported it from the very beginning, with a stack and user-defined compound types. Case in point: Lex/Yacc, which use global names (and state) by default. Now however, instantiation is so pervasive (global variables are assumed evil by default), that we don't even call it OO any more. We just call it good practice.
- flavio81 9y ago>The real advantage of OOP, as used today in Java/C++, is instantiation. Instead of having procedures working on global variables, you have procedure working on local variables, including complex data structures. You can have the same in functional programming, by creating closures on demand.
- loup-vaillant 9y agoAs a long time FP advocate, I know. Instantiation just happens to be one of the things OOP claimed, for a time, to be the sole purveyor of.
- jstimpfle 9y ago> Now however, instantiation is so pervasive (global variables are assumed evil by default), that we don't even call it OO any more. We just call it good practice. This is another one of my pet peeves... If it's global (a static resource), make it a global. Local variables for static resources make code so much less readable. The only argument against globals is testing, and that's only an argument because common OO languages have no support for resetting global "objects"! Solution: Just don't use OO syntax in the first place - it's wrong. Just write init() and exit() functions.
- jstimpfle 9y ago> Don’t all pieces have a location? Make a table containing locations for each piece. > Aren’t all pieces movable? Make a function ("procedure") that moves a piece (e.g. edits the location table). > Might we want to display pieces? Make a render function (e.g. gets a piece type and a position) > Do we want to journal them to files to save game state, or their moves to streams to play remotely? Write serialization and deserialization routines (again, procedures that get piece type and position). No need to cram that in to some idea of piece "class". That only glues things together that don't belong together. OO is pretty much crap.
- valuearb 9y agoPeople who say this apparently have an inordinate love of switch statements.
- jstimpfle 9y agoCome on, please don't claim that you need to add more piece types independently so absolutely need virtual functions. That's hilarious for a chess game (and most other applications), but even if that was needed, one could still pass function pointers in those few places. Anyway: No, they design their program to be efficient and readable. There is more often than not an alternative to switch statements: don't mix data of different types together. (Where by types I don't mean crazy artificial types built with a modern language -- but with regards to implementation of a functionality). If this is about drawing chess pieces, you need only a single draw function for all of them. Just maintain a table that maps a piece to its material (sprite, mesh, whatever). Or alternatively, have a table that maps pieces to "types" and another static one that maps these types to materials. (Much better: Materialized type to simple enum. Can actually use this information, as opposed to overhyped static types). More general answer: The best way to do it is usually not a switch statement but a data table. Because usually the switching is not about behaviour, but about data. (Not that switch statements are so bad). Code gets so so simple, robust, and maintainable if developers are not preconcerned about static types, OO, and whatnot.
- Silhouette 9y agoI'm not sure why that's apparent, but even if it is, is there any reason to believe that switch statements (or pattern matching, or look-up tables, or other related language constructs) couldn't handle any plausible requirement in this case?