Friday, October 16, 2009

Classics

Smalltalk's treatment of all constructs as instances of a very few primitives makes it a fundamentally very simple language.  This is not to say that it's necessarily easy to express an idea in the language, but rather just that the language itself is compact.  Using these constructs alone allow it to reason using a common fundamental model, rather than having to worry about the semantics of a plethora of language constructs.  Messages, specifically, make it easier to perform code analysis related to interactions of code blocks, and therefore make it easier to express algorithms in a way that will be more conducive to parallelization.

Programming and design using inheritance is generally a mixed blessing.  To the extent that the system grows in the anticipated manner, inheritance works great to encapsulate functionality and reuse code.  It's when one or more of the fundamental assumptions of the inheritance model are challenged that the headaches begin.  At that point, you either have to rework your entire inheritance hierarchy to be consistent with the updated model, and incur the risk of breaking something, or hack in an ill fitting subclass which breaks the fundamental reasoning about the system, but not the implementation--either way, this breaks something.  I think in very well understood domains, inheritance works well, but in arenas with rapidly changing requirements and/or models which are not very well understood, inheritance leaves something to be desired.

Regarding dynamic dispatch, this is essentially a similar method to that used in C++ inheritance, using a virtual method table.  It's just another level of indirection in memory, and we've seen time and time again levels of indirection added to software to solve problems of complexity, so I don't feel that this one additional layer would do much to change the overall scalability of the software.

The open nature of Smalltalk classes violates the principle that a system should be "open to extension, but closed to modification".  While it's useful to ensure that no arbitrary constraints are put in place, it could certainly pose problems for maintenance.  Whereas in other languages you might declare a class as "final" or "sealed", such that you would be free to modify its structure whilst maintaining the external interface, leaving classes open to modification would make these types of changes more likely to break other code.

While the chapter argues that compile-time checking can garner a false sense of security, it has been my experience that when dealing with applications heavy in definition/data, and dealing less with complex algorithms, static typing and design/compile time tools/checking can go a long way to making an application sound.  While it doesn't ensure that the program executes without error and generates the correct output, it at least ensures that the types of operations that are occurring are semantically valid, and by building a smart type structure in the program, this can provide a great number of advantages.  Metaprogramming requires good code coverage from a test suite before it can touch the kind of whole-program checking that statically typed languages can offer.

No comments:

Post a Comment