Problem with asClass usage
Hi We want to raise a strong warning against the extension of the use of asClass and friends. asClass should not be used in Pharo distribution. I will propose to deprecate it. We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems. I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies. First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization. Second, at least use self class environment at: #foo Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually. Imagine that tomorrow your code is in its own module. Then you want to know from your code point of you if a binding exist not from the one of environment in which String is. here are some examples: ============================== quadrangleClass ^ 'QuadrangleForTesting' asClass Strange it simply breaks. Of course it broke the smallLint rule. ============================== Metacello should better define OSProcess as a dependent.Because it is not clear what will happen if if not there? extractRepositoryFrom: zipFile to: directory "unzip <zipFile> into <directory>" | out err proc errorMessage | out := FileStream forceNewFileNamed: '/tmp/zip.out'. err := FileStream forceNewFileNamed: '/tmp/zip.err'. errorMessage := ''. [ proc := #OSProcess asClass thisOSProcess forkJob: '/usr/bin/unzip' arguments: {'-u'. zipFile. '-d'. directory} environment: nil descriptors: (Array with: nil with: out with: err). ================== I do not get why we need this funky logic. openInBrickWindowLabeled: aLabel #GLMSystemWindowBrick asClassIfAbsent: [ ^ self asMorph openInWindow ]. ^ #GLMSystemWindowBrick asClass new label: aLabel; color: Color transparent; addBrickBack: ( GLMBrick new vSpaceFill window "Answer the receiver's window." #GLMWindowBrick asClassIfAbsent: [ ^ self ownerThatIsA: SystemWindow ]. ^ (self ownerThatIsA: #GLMWindowBrick asClass) ifNil: [ self ownerThatIsA: SystemWindow ] sendUsageData: aBoolean | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ self ]. ^ settingsClass sendUsageData: aBoolean sendUsageData | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ false ]. ^ settingsClass sendUsageData
I believe #asClass itself was introduced for a use case to simplify Workspace "user interactive" Gofer scripts to retrieve and load Configurations. Since this is through away code its not covered by your modularity concerns, and I'm not sure if it came before or after its friends, but can we retain or substitute something to avoid needing ugly "(Smalltalk at: #ConfigurationOfXXX) load" ? This is a "first impression" consideration for people dealing with Configurations for the first time (even thought we now have Configuration Browser). The use case is that newbies will copy-paste a script from a web site to Playground and execute the whole script resulting in a error "Unknown class ConfigurationOfXXX." They don't know to execute in two separate steps, first "Gofer ... load" then "ConfigurationOfXXX load". Alternatively, what if the Metacello package extended Gofer with a method #configurationOf: so websites can show... config := Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' "return class ConfigurationOfXXX" config load. ...so the compiler is dealing with a variable "config" rather than class 'ConfigurationOfXXX' that it doesn't know yet, or a further altenative... Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' do: [ :config | config load ]; configurationOf: 'YYY' do: [ :config | config load ]. cheers -ben On 10/04/2015 4:32 am, "stepharo" <stepharo@free.fr> wrote:
Hi
We want to raise a strong warning against the extension of the use of asClass and friends. asClass should not be used in Pharo distribution. I will propose to deprecate it.
We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems.
I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies.
First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization.
Second, at least use self class environment at: #foo
Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually.
Imagine that tomorrow your code is in its own module. Then you want to know from your code point of you if a binding exist not from the one of environment in which String is.
here are some examples:
============================== quadrangleClass ^ 'QuadrangleForTesting' asClass
Strange it simply breaks. Of course it broke the smallLint rule.
============================== Metacello should better define OSProcess as a dependent.Because it is not clear what will happen if if not there?
extractRepositoryFrom: zipFile to: directory "unzip <zipFile> into <directory>"
| out err proc errorMessage | out := FileStream forceNewFileNamed: '/tmp/zip.out'. err := FileStream forceNewFileNamed: '/tmp/zip.err'. errorMessage := ''. [ proc := #OSProcess asClass thisOSProcess forkJob: '/usr/bin/unzip' arguments: {'-u'. zipFile. '-d'. directory} environment: nil descriptors: (Array with: nil with: out with: err).
==================
I do not get why we need this funky logic.
openInBrickWindowLabeled: aLabel
#GLMSystemWindowBrick asClassIfAbsent: [ ^ self asMorph openInWindow ].
^ #GLMSystemWindowBrick asClass new label: aLabel; color: Color transparent; addBrickBack: ( GLMBrick new vSpaceFill
window "Answer the receiver's window." #GLMWindowBrick asClassIfAbsent: [ ^ self ownerThatIsA: SystemWindow ].
^ (self ownerThatIsA: #GLMWindowBrick asClass) ifNil: [ self ownerThatIsA: SystemWindow ]
sendUsageData: aBoolean | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ self ]. ^ settingsClass sendUsageData: aBoolean
sendUsageData | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ false ]. ^ settingsClass sendUsageData
Le 10/4/15 06:09, Ben Coman a écrit :
I believe #asClass itself was introduced for a use case to simplify Workspace "user interactive" Gofer scripts to retrieve and load Configurations. Since this is through away code its not covered by your modularity concerns, and I'm not sure if it came before or after its friends, but can we retain or substitute something to avoid needing ugly "(Smalltalk at: #ConfigurationOfXXX) load" ?
For first time newbee they can also use the Configuration browser. This is one click.
This is a "first impression" consideration for people dealing with Configurations for the first time (even thought we now have Configuration Browser). The use case is that newbies will copy-paste a script from a web site to Playground and execute the whole script resulting in a error "Unknown class ConfigurationOfXXX." They don't know to execute in two separate steps, first "Gofer ... load" then "ConfigurationOfXXX load". Yes it would be much better.
Alternatively, what if the Metacello package extended Gofer with a method #configurationOf: so websites can show... config := Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' "return class ConfigurationOfXXX" config load. ...so the compiler is dealing with a variable "config" rather than class 'ConfigurationOfXXX' that it doesn't know yet, or a further altenative... Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' do: [ :config | config load ]; configurationOf: 'YYY' do: [ :config | config load ]. cheers -ben On 10/04/2015 4:32 am, "stepharo" <stepharo@free.fr <mailto:stepharo@free.fr>> wrote:
Hi
We want to raise a strong warning against the extension of the use of asClass and friends. asClass should not be used in Pharo distribution. I will propose to deprecate it.
We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems.
I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies.
First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization.
Second, at least use self class environment at: #foo
Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually.
Imagine that tomorrow your code is in its own module. Then you want to know from your code point of you if a binding exist not from the one of environment in which String is.
here are some examples:
============================== quadrangleClass ^ 'QuadrangleForTesting' asClass
Strange it simply breaks. Of course it broke the smallLint rule.
============================== Metacello should better define OSProcess as a dependent.Because it is not clear what will happen if if not there?
extractRepositoryFrom: zipFile to: directory "unzip <zipFile> into <directory>"
| out err proc errorMessage | out := FileStream forceNewFileNamed: '/tmp/zip.out'. err := FileStream forceNewFileNamed: '/tmp/zip.err'. errorMessage := ''. [ proc := #OSProcess asClass thisOSProcess forkJob: '/usr/bin/unzip' arguments: {'-u'. zipFile. '-d'. directory} environment: nil descriptors: (Array with: nil with: out with: err).
==================
I do not get why we need this funky logic.
openInBrickWindowLabeled: aLabel
#GLMSystemWindowBrick asClassIfAbsent: [ ^ self asMorph openInWindow ].
^ #GLMSystemWindowBrick asClass new label: aLabel; color: Color transparent; addBrickBack: ( GLMBrick new vSpaceFill
window "Answer the receiver's window." #GLMWindowBrick asClassIfAbsent: [ ^ self ownerThatIsA: SystemWindow ].
^ (self ownerThatIsA: #GLMWindowBrick asClass) ifNil: [ self ownerThatIsA: SystemWindow ]
sendUsageData: aBoolean | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ self ]. ^ settingsClass sendUsageData: aBoolean
sendUsageData | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ false ]. ^ settingsClass sendUsageData
Why not add this to the critic browser? I'm quite guilty of doing this myself... because it is easier than spending X amount of time of coming up with proper abstraction for unimportant stuff instead of focusing on what I need.... Peter On Fri, Apr 10, 2015 at 8:07 AM, stepharo <stepharo@free.fr> wrote:
Le 10/4/15 06:09, Ben Coman a écrit :
I believe #asClass itself was introduced for a use case to simplify Workspace "user interactive" Gofer scripts to retrieve and load Configurations. Since this is through away code its not covered by your modularity concerns, and I'm not sure if it came before or after its friends, but can we retain or substitute something to avoid needing ugly "(Smalltalk at: #ConfigurationOfXXX) load" ?
For first time newbee they can also use the Configuration browser. This is one click.
This is a "first impression" consideration for people dealing with Configurations for the first time (even thought we now have Configuration Browser). The use case is that newbies will copy-paste a script from a web site to Playground and execute the whole script resulting in a error "Unknown class ConfigurationOfXXX." They don't know to execute in two separate steps, first "Gofer ... load" then "ConfigurationOfXXX load".
Yes it would be much better.
Alternatively, what if the Metacello package extended Gofer with a method #configurationOf: so websites can show...
config := Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' "return class ConfigurationOfXXX" config load.
...so the compiler is dealing with a variable "config" rather than class 'ConfigurationOfXXX' that it doesn't know yet, or a further altenative...
Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' do: [ :config | config load ]; configurationOf: 'YYY' do: [ :config | config load ].
cheers -ben
On 10/04/2015 4:32 am, "stepharo" <stepharo@free.fr> wrote:
Hi
We want to raise a strong warning against the extension of the use of asClass and friends. asClass should not be used in Pharo distribution. I will propose to deprecate it.
We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems.
I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies.
First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization.
Second, at least use self class environment at: #foo
Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually.
Imagine that tomorrow your code is in its own module. Then you want to know from your code point of you if a binding exist not from the one of environment in which String is.
here are some examples:
============================== quadrangleClass ^ 'QuadrangleForTesting' asClass
Strange it simply breaks. Of course it broke the smallLint rule.
============================== Metacello should better define OSProcess as a dependent.Because it is not clear what will happen if if not there?
extractRepositoryFrom: zipFile to: directory "unzip <zipFile> into <directory>"
| out err proc errorMessage | out := FileStream forceNewFileNamed: '/tmp/zip.out'. err := FileStream forceNewFileNamed: '/tmp/zip.err'. errorMessage := ''. [ proc := #OSProcess asClass thisOSProcess forkJob: '/usr/bin/unzip' arguments: {'-u'. zipFile. '-d'. directory} environment: nil descriptors: (Array with: nil with: out with: err).
==================
I do not get why we need this funky logic.
openInBrickWindowLabeled: aLabel
#GLMSystemWindowBrick asClassIfAbsent: [ ^ self asMorph openInWindow ].
^ #GLMSystemWindowBrick asClass new label: aLabel; color: Color transparent; addBrickBack: ( GLMBrick new vSpaceFill
window "Answer the receiver's window." #GLMWindowBrick asClassIfAbsent: [ ^ self ownerThatIsA: SystemWindow ].
^ (self ownerThatIsA: #GLMWindowBrick asClass) ifNil: [ self ownerThatIsA: SystemWindow ]
sendUsageData: aBoolean | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ self ]. ^ settingsClass sendUsageData: aBoolean
sendUsageData | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ false ]. ^ settingsClass sendUsageData
Le 10 avr. 2015 08:10, "Peter Uhnák" <i.uhnak@gmail.com> a écrit :
Why not add this to the critic browser?
I'm quite guilty of doing this myself... because it is easier than
spending X amount of time of coming up with proper abstraction for unimportant stuff instead of focusing on what I need.... Same. It is very useful to get code loading in a shorter way that Smalltalk at: ... #ConfigurationOfX asClass ... is nicer than the other longer version. For the GLM things, I guess it allows one to have code that works only if an extra module is loaded. We have asString and it is fine. Now asClass will not be. Duh? aThing perform: #someAction is as complicated. Yeah make a lint rule but do not disallow the usage. Phil
Peter
On Fri, Apr 10, 2015 at 8:07 AM, stepharo <stepharo@free.fr> wrote:
Le 10/4/15 06:09, Ben Coman a écrit :
I believe #asClass itself was introduced for a use case to simplify
Workspace "user interactive" Gofer scripts to retrieve and load Configurations. Since this is through away code its not covered by your modularity concerns, and I'm not sure if it came before or after its friends, but can we retain or substitute something to avoid needing ugly "(Smalltalk at: #ConfigurationOfXXX) load" ?
For first time newbee they can also use the Configuration browser. This is one click.
This is a "first impression" consideration for people dealing with
Configurations for the first time (even thought we now have Configuration Browser). The use case is that newbies will copy-paste a script from a web site to Playground and execute the whole script resulting in a error "Unknown class ConfigurationOfXXX." They don't know to execute in two separate steps, first "Gofer ... load" then "ConfigurationOfXXX load".
Yes it would be much better.
Alternatively, what if the Metacello package extended Gofer with a
method #configurationOf: so websites can show...
config := Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' "return class ConfigurationOfXXX" config load.
...so the compiler is dealing with a variable "config" rather than
class 'ConfigurationOfXXX' that it doesn't know yet, or a further altenative...
Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' do: [ :config | config load ]; configurationOf: 'YYY' do: [ :config | config load ].
cheers -ben
On 10/04/2015 4:32 am, "stepharo" <stepharo@free.fr> wrote:
Hi
We want to raise a strong warning against the extension of the use of
asClass and friends.
asClass should not be used in Pharo distribution. I will propose to deprecate it.
We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems.
I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies.
First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization.
Second, at least use self class environment at: #foo
Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually.
Imagine that tomorrow your code is in its own module. Then you want to know from your code point of you if a binding exist not from the one of environment in which String is.
here are some examples:
============================== quadrangleClass ^ 'QuadrangleForTesting' asClass
Strange it simply breaks. Of course it broke the smallLint rule.
============================== Metacello should better define OSProcess as a dependent.Because it is not clear what will happen if if not there?
extractRepositoryFrom: zipFile to: directory "unzip <zipFile> into <directory>"
| out err proc errorMessage | out := FileStream forceNewFileNamed: '/tmp/zip.out'. err := FileStream forceNewFileNamed: '/tmp/zip.err'. errorMessage := ''. [ proc := #OSProcess asClass thisOSProcess forkJob: '/usr/bin/unzip' arguments: {'-u'. zipFile. '-d'. directory} environment: nil descriptors: (Array with: nil with: out with: err).
==================
I do not get why we need this funky logic.
openInBrickWindowLabeled: aLabel
#GLMSystemWindowBrick asClassIfAbsent: [ ^ self asMorph openInWindow ].
^ #GLMSystemWindowBrick asClass new label: aLabel; color: Color transparent; addBrickBack: ( GLMBrick new vSpaceFill
window "Answer the receiver's window." #GLMWindowBrick asClassIfAbsent: [ ^ self ownerThatIsA: SystemWindow ].
^ (self ownerThatIsA: #GLMWindowBrick asClass) ifNil: [ self ownerThatIsA: SystemWindow ]
sendUsageData: aBoolean | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ self ]. ^ settingsClass sendUsageData: aBoolean
sendUsageData | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ false ]. ^ settingsClass sendUsageData
Le 10 avr. 2015 à 06:09, Ben Coman a écrit :
I believe #asClass itself was introduced for a use case to simplify Workspace "user interactive" Gofer scripts to retrieve and load Configurations. Since this is through away code its not covered by your modularity concerns, and I'm not sure if it came before or after its friends, but can we retain or substitute something to avoid needing ugly "(Smalltalk at: #ConfigurationOfXXX) load" ?
This is a "first impression" consideration for people dealing with Configurations for the first time (even thought we now have Configuration Browser). The use case is that newbies will copy-paste a script from a web site to Playground and execute the whole script resulting in a error "Unknown class ConfigurationOfXXX." They don't know to execute in two separate steps, first "Gofer ... load" then "ConfigurationOfXXX load".
Alternatively, what if the Metacello package extended Gofer with a method #configurationOf: so websites can show...
config := Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' "return class ConfigurationOfXXX" config load.
...so the compiler is dealing with a variable "config" rather than class 'ConfigurationOfXXX' that it doesn't know yet, or a further altenative...
Gofer new url: 'http://smalltalkhub.com/mc/MyProject/main' package: 'MyXXXPackage'; load; configurationOf: 'XXX' do: [ :config | config load ]; configurationOf: 'YYY' do: [ :config | config load ].
cheers -ben
It is not a problem anymore. We have better ways to load a configuration and the associated packages: Metacello new configuration: 'XXX'; squeaksource3: 'MyProject'; version: '0.9.0'; load. Le 10 avr. 2015 à 08:57, phil@highoctane.be a écrit :
For the GLM things, I guess it allows one to have code that works only if an extra module is loaded.
We have asString and it is fine. Now asClass will not be. Duh?
aThing perform: #someAction is as complicated.
Yeah make a lint rule but do not disallow the usage.
The problem is that if you want to allow to browse remote code or to have 2 versions of the same class in the system for example, aSymbol asClass will not work. It will always search the class in the environment of the String class. The resolution of a symbol should be the responsibility of Environment. asString does not have the same problem. To me, #perform: is not a problem because the resolution of the selector is done by the class. I don't see a case where you do not want that. Christophe.
On 10/04/2015 4:32 am, "stepharo" <stepharo@free.fr> wrote: Hi
We want to raise a strong warning against the extension of the use of asClass and friends. asClass should not be used in Pharo distribution. I will propose to deprecate it.
We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems.
I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies.
First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization.
Second, at least use self class environment at: #foo
Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually.
Imagine that tomorrow your code is in its own module. Then you want to know from your code point of you if a binding exist not from the one of environment in which String is.
here are some examples:
============================== quadrangleClass ^ 'QuadrangleForTesting' asClass
Strange it simply breaks. Of course it broke the smallLint rule.
============================== Metacello should better define OSProcess as a dependent.Because it is not clear what will happen if if not there?
extractRepositoryFrom: zipFile to: directory "unzip <zipFile> into <directory>"
| out err proc errorMessage | out := FileStream forceNewFileNamed: '/tmp/zip.out'. err := FileStream forceNewFileNamed: '/tmp/zip.err'. errorMessage := ''. [ proc := #OSProcess asClass thisOSProcess forkJob: '/usr/bin/unzip' arguments: {'-u'. zipFile. '-d'. directory} environment: nil descriptors: (Array with: nil with: out with: err).
==================
I do not get why we need this funky logic.
openInBrickWindowLabeled: aLabel
#GLMSystemWindowBrick asClassIfAbsent: [ ^ self asMorph openInWindow ].
^ #GLMSystemWindowBrick asClass new label: aLabel; color: Color transparent; addBrickBack: ( GLMBrick new vSpaceFill
window "Answer the receiver's window." #GLMWindowBrick asClassIfAbsent: [ ^ self ownerThatIsA: SystemWindow ].
^ (self ownerThatIsA: #GLMWindowBrick asClass) ifNil: [ self ownerThatIsA: SystemWindow ]
sendUsageData: aBoolean | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ self ]. ^ settingsClass sendUsageData: aBoolean
sendUsageData | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ false ]. ^ settingsClass sendUsageData
Ben Coman wrote
I believe #asClass itself was introduced for a use case to simplify Workspace "user interactive" Gofer scripts to retrieve and load Configurations.
Yes. But it's no longer necessary due to... Ben Coman wrote
extended Gofer with a method #configurationOf:
We already have this :) Gofer it ... configurationOf: 'MyCoolProject'; loadStable. So there is no conflict: 1. Use the new Gofer API in the workspace (or the Metacello one Christophe pointed out) 2. Handle dependencies like we did for decades prior to #asClass ;) 3. Remove #asClass before it poisons our beloved system!!! ----- Cheers, Sean -- View this message in context: http://forum.world.st/Problem-with-asClass-usage-tp4818686p4818861.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
Hi, The Gofer script does not solve the problem of triggering a special loading selector in the ConfigurationOfXYZ. Furthermore, asClass can be used for other usages as well, but it is clear that it is intended for scripts and not for production code. For example, I recently sent around a script that showed this: Object subclass: #AClass instanceVariableNames: '' classVariableNames: '' category: 'XYZ'. #AClass asClass compile: 'someMethod'. ... I do agree that checking the existence of classes should not happen explicitly in code. For example, the code in Brick that checks for classes should not exist at all. However, removing asClass will only change the way a class can be looked up from a string. It will still not prevent people to look classes up by symbols in the code. In my mind: - saying: "#AClass asClass" - should have the same semantics as saying "AClass" All in all, I think asClass has a legitimate usage, but we should certainly combat explicit class checking in code. Cheers, Doru
On Fri, Apr 10, 2015 at 2:35 PM, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi,
The Gofer script does not solve the problem of triggering a special loading selector in the ConfigurationOfXYZ. Furthermore, asClass can be used for other usages as well, but it is clear that it is intended for scripts and not for production code. For example, I recently sent around a script that showed this:
Object subclass: #AClass instanceVariableNames: '' classVariableNames: '' category: 'XYZ'. #AClass asClass compile: 'someMethod'. ...
That's how some methods are patched upon system startup in a startup script of mine. Some value ranges etc can be set by a sysadmin in a couple files.
I do agree that checking the existence of classes should not happen explicitly in code. For example, the code in Brick that checks for classes should not exist at all.
However, removing asClass will only change the way a class can be looked up from a string. It will still not prevent people to look classes up by symbols in the code. In my mind: - saying: "#AClass asClass" - should have the same semantics as saying "AClass"
+1
All in all, I think asClass has a legitimate usage, but we should certainly combat explicit class checking in code.
+1 x 2
Cheers, Doru
-- --- Philippe Back Visible Performance Improvements Mob: +32(0) 478 650 140 | Fax: +32 (0) 70 408 027 Mail:phil@highoctane.be | Web: http://philippeback.eu Blog: http://philippeback.be | Twitter: @philippeback Youtube: http://www.youtube.com/user/philippeback/videos High Octane SPRL rue cour Boisacq 101 | 1301 Bierges | Belgium Pharo Consortium Member - http://consortium.pharo.org/ Featured on the Software Process and Measurement Cast - http://spamcast.libsyn.com Sparx Systems Enterprise Architect and Ability Engineering EADocX Value Added Reseller
Tudor Girba-2 wrote
The Gofer script does not solve the problem of triggering a special loading selector in the ConfigurationOfXYZ.
Can you give an example? You mean like loading a particular group? As Christophe mentioned, we have the Metacello scripting API now: Metacello new configuration: 'Magritte3'; smalltalkhubUser: 'Magritte' project: 'Magritte3'; version: #bleedingEdge; load: 'Morphic'. "<------------- Load specific group" Tudor Girba-2 wrote
but it is clear that it is intended for scripts and not for production code.
It's not clear to everyone given Steph's OP ;) So how do we enforce it? I'm guessing most of the users who don't know that they shouldn't use #asClass are probably not running Lint checks (or don't even know about them) ----- Cheers, Sean -- View this message in context: http://forum.world.st/Problem-with-asClass-usage-tp4818686p4818998.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
On 04/10/2015 05:35 AM, Tudor Girba wrote:
Hi,
The Gofer script does not solve the problem of triggering a special loading selector in the ConfigurationOfXYZ.
Frankly I have been saying for years that things like this should not be done and that folks should be prepared for the day when a configuration is no longer a class .... not quite there yet, but I guess this is the first shot across the bow ... Sending messages to a configuration should no longer be used ... I will eventually deprecate that style of loading in favor of the "scripting api style" ... the new style of loading makes use of a registry that records the actual version of projects that were loaded. The old style relied upon a calculation of "currentVersion" and "currentVersion" besides being excruciatingly slow, was often inaccurate ... there is a whole class of bugs that are eliminated by the "scripting api" ... there are also a whole slug of new features that are available when using the "scripting api". Configurations are SUPPOSED to be platform neutral, so including magical, arbitrary Smalltalk expressions as part of the required load sequence is just right out of bounds from the get go ... I know that folks have done all kinds of "clever tricks" over the years with configurations taking advantage of the fact that they are classes and early on I did make noise whenever I saw someone doing that ... but I could only warn folks that it was not a good idea and since "boys will be boys" this practice has continued and my protests fell on deaf ears ... With all of this said, I am curious as to is so special about these class-side selectors that they cannot be accomplished through the existing "scripting api" ... there are already facilities for execution "arbitrary code" within the configuration framework that does respect the platform boundaries, so I would imagine that most of the cases can be converted ... Sooo if there are problem areas I would be interested in understanding the use cases ... Dale
On Fri, Apr 10, 2015 at 7:44 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Ben Coman wrote
I believe #asClass itself was introduced for a use case to simplify Workspace "user interactive" Gofer scripts to retrieve and load Configurations.
Yes. But it's no longer necessary due to...
Ben Coman wrote
extended Gofer with a method #configurationOf:
We already have this :)
Gofer it ... configurationOf: 'MyCoolProject'; loadStable.
So there is no conflict: 1. Use the new Gofer API in the workspace (or the Metacello one Christophe pointed out)
ahhh, cool. The rest sounds fine then. cheers -ben
2. Handle dependencies like we did for decades prior to #asClass ;) 3. Remove #asClass before it poisons our beloved system!!!
Hi 2015-04-08 13:32 GMT+03:00 stepharo <stepharo@free.fr>:
Hi
We want to raise a strong warning against the extension of the use of asClass and friends. asClass should not be used in Pharo distribution. I will propose to deprecate it.
We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems.
I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies.
First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization.
Second, at least use self class environment at: #foo
Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually.
To me it means that #asClass has wrong implementation and should be fixed like: String>>asClass thisContext sender class environment at: self Because users of code "'className' asClass" obviously want class from sender class environment.
Hi, To make it easier to refactor these places, here is how to find asClass usages with GTSpotter: http://www.humane-assessment.com/blog/finding-asclass-usages-in-glamour-usin... :) Cheers, Doru On Wed, Apr 8, 2015 at 12:32 PM, stepharo <stepharo@free.fr> wrote:
Hi
We want to raise a strong warning against the extension of the use of asClass and friends. asClass should not be used in Pharo distribution. I will propose to deprecate it.
We are working on dependency analysis, module system, remote debugging and asClass introduces lose class references and many related problems.
I would like to remove this behavior because it is clear that it will just grow up and lead to deadcode and ugly dependencies.
First, most of the time you can avoid to query Smalltalk globals at: and that BY CONSTRUCTION a software system should be built and it should define its own customization.
Second, at least use self class environment at: #foo
Why is it much much much better? because it does not rely on String class resolution and as such is much more modular. You do not want to have the resolution of a symbol related to the place where String is defined but on where your code is actually.
Imagine that tomorrow your code is in its own module. Then you want to know from your code point of you if a binding exist not from the one of environment in which String is.
here are some examples:
============================== quadrangleClass ^ 'QuadrangleForTesting' asClass
Strange it simply breaks. Of course it broke the smallLint rule.
============================== Metacello should better define OSProcess as a dependent.Because it is not clear what will happen if if not there?
extractRepositoryFrom: zipFile to: directory "unzip <zipFile> into <directory>"
| out err proc errorMessage | out := FileStream forceNewFileNamed: '/tmp/zip.out'. err := FileStream forceNewFileNamed: '/tmp/zip.err'. errorMessage := ''. [ proc := #OSProcess asClass thisOSProcess forkJob: '/usr/bin/unzip' arguments: {'-u'. zipFile. '-d'. directory} environment: nil descriptors: (Array with: nil with: out with: err).
==================
I do not get why we need this funky logic.
openInBrickWindowLabeled: aLabel
#GLMSystemWindowBrick asClassIfAbsent: [ ^ self asMorph openInWindow ].
^ #GLMSystemWindowBrick asClass new label: aLabel; color: Color transparent; addBrickBack: ( GLMBrick new vSpaceFill
window "Answer the receiver's window." #GLMWindowBrick asClassIfAbsent: [ ^ self ownerThatIsA: SystemWindow ].
^ (self ownerThatIsA: #GLMWindowBrick asClass) ifNil: [ self ownerThatIsA: SystemWindow ]
sendUsageData: aBoolean | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ self ]. ^ settingsClass sendUsageData: aBoolean
sendUsageData | settingsClass | settingsClass := #GTSpotterEventRecorderSettings asClassIfAbsent: [ ^ false ]. ^ settingsClass sendUsageData
-- www.tudorgirba.com "Every thing has its own flow"
participants (9)
-
Ben Coman -
Christophe Demarey -
Dale Henrichs -
Denis Kudriashov -
Peter Uhnák -
phil@highoctane.be -
Sean P. DeNigris -
stepharo -
Tudor Girba