Single responsibility in smalltalk
Asked Answered
B

3

7

If the Single Responsibility Principle applies to OOP and smalltalk (&ruby as well) is considered as one of the most OO languages why can Object class respond to so many messages?

Just a few from Object methodDict explore:

  • inspect, explore, browse, print: on:
  • accept (visitor pattern on all objects?)
  • copy, deepCopy, join, joinTo, at:, at: modify:
  • asString, asFunction, asOrderedCollection (why not asSet also?)
  • seaside ones: asLink, asJson, asJavascript

It is not object's responsibility (for example user domain model should be interested only in its private messages, payments, etc.)

EDIT: some of them are meaningful (asString, asOrderedCollection, accept, notify) while others seems pretty weird (at:, asFunction, deepCopy, join, joinTo)

Bunting answered 31/1, 2011 at 8:31 Comment(4)
Whoaa, and we complain that .NET's Object class is too big (it has only 7 methods total)!Frizzy
Heh, Object.new has 56 methods in ruby 1.9.2 .Palaeolithic
There are 370 methods in Object methodDict in Seaside (based on pharo smalltalk) image :-)Ruction
Well, Smalltalk is old. Why did you think the single responsibility principle was invented?Interrelation
C
8

You have to consider the modularity features of Smalltalk. Namely, method definitions are independent from class definitions, so methods on Object can be packaged with the application they relate to (e.g., Seaside). These extension methods are not part of the base system, so they only add responsibilities to their class from the point of view of the package they belong to. Many of these methods are simple double-dispatch points: if anObject asFoo simply delegates to Foo fromObject: anObject, I wouldn't say it adds much responsibility to the class.

Reflective methods like inspect, copy, deepCopy conceptually have their place on Object, but I agree that there are better architectures for reflection (Mirrors).

Now, Smalltalk might be an ideal with beautiful principles, but you have to take particular implementations with a grain of salt :)

Smalltalk systems have a tendency to evolve into big monolithic systems, because it's so easy to change the base system, and because it's tempting to use the image as a development artifact, bypassing good practices of continuous integration. In the end, a lot of these funny class responsibilities are due to historical/practical reasons; this is especially true of Squeak, because it was primarily developed as a platform for fast multimedia experimentation, rather than for software engineering education or industry purposes (which Pharo aims to be).

Confederation answered 31/1, 2011 at 15:26 Comment(8)
thx for answer & interesting reading! To me objectInstance class appears to be more logical & handy than reflectorInstance reflect objectInstance getClass PHP does it this way and I just don't like it (and there are cases where it would be cool to return reflection proxy - for particular classes)Ruction
The problem here is that classes have a dual role: 1) as a modeling concept: it makes sense to have anObject class to access factory methods, class variables, etc. 2) as a runtime mechanism/program entity: this is clearly meta-level needed by the compiler/version control/IDE, but that domain code should not access.Confederation
I don't agree with you on this - see on ruby's act_as_whatever methods - they dynamically adds methods to class - how would you implement this? It is useful even for attr_accessor generationRuction
These metaprogramming methods are needed in Ruby because developers have to deal with text files. In Smalltalk, we modify the running program as living objects, so metaprogramming is done via one-time IDE commands, and very rarely appears in domain code. There is no macro facility like in Lisp. For accessors, we just tell the browser to please generate them, and it creates 2 new methods. Same for refactorings. For more complex stuff we could generate whole classes if needed, but that is not common practice.Confederation
Seems like better approach (all supported messages are shown in IDE) - but still I think that object should know about its class and could use it let's say for some db-mapping stuff. EDIT: IDE/Compiler are objects as well as domain classes are - why is it so bad to leave it public accessible?Ruction
1) We agree. What I'm saying is that a class has both a domain role and a meta role, and they should be played by separate entities. Some of the reflection API is useful, some is black magic that you don't want anywhere near a production application. 2) Why is it be bad to leave /usr/bin or /sbin writeable to anyone?Confederation
2) Separate ReflectionClass does not solve this (it can be still writable) 1) I don't think so - what is example of class domain role? factories?Ruction
factories are the most obvious, but also singletons, constants or settings, metadescriptions in Magritte...Confederation
A
6

A few reasons:

  • Object and ProtoObject are the basis of Smalltalk's object model, so it's normal that they have big responsibilities, like taking care of copy, serialization, etc.
  • The law of Demeter may be more important here: who will take care of these functions, if not the Object itself?
  • A lot of these functions are there for debugging and representation purposes. You could work without browse, explore and inspect (but they're really useful).

Essentially, all these messages represent everything an object can do, and there's a lot of things you can do.

Aldon answered 31/1, 2011 at 9:41 Comment(0)
D
0

Because in Smalltalk - everything is an object, and the root Object class essentially has to govern all system behaviour, including the Class hierarchy (as all Classes are objects) and the Metaclass hierarchy.

With great power comes great responsibility.

In other systems, where the objects are simply a subdomain of the entire system, Object does not have to do so much, and so does not need to be given so many named responsibilities.

Dusa answered 13/11, 2015 at 1:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.