tag:blogger.com,1999:blog-75336277067653658572024-03-13T10:51:57.670-04:00Learning SmalltalkFirst of all, this is not a blog which will teach you Smalltalk, rather it is an online notepad of my attempts to learn the language. Look upon this blog as a list of sudden insights and moments of overcoming stupidity!Unknownnoreply@blogger.comBlogger84125tag:blogger.com,1999:blog-7533627706765365857.post-35611478780078749352010-07-21T15:40:00.000-04:002010-07-21T15:40:14.471-04:00I love not having to think about storing dataI am finally getting around to building some useful tools in Pharo. I will try to capture more of my learnings as I go along. However, I was struck by something today that really warrants commentary.<br />
<br />
One of the really great things about Smalltalk (and Gemstone - when I get to use that), is that one stops thinking about data storage. I have become so used to reading and writing to my objects - without the normal data marshalling - that I hadn't realised just how much easier it has made my life.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-23063773444316174052009-09-22T16:57:00.002-04:002009-09-22T17:01:18.075-04:00No, seriously, XMPP really does rock!As you can see from Peter's comment on my previous post, the XMPP integration is really cool. However, it is also something that one has to experience to really understand.<br /><br />I added the app to the chat window in my gmail account. The app instantly appeared as being online. I typed in a few messages and they either controlled windows, or wrote to the transcript.<br /><br />Now, clearly this is not some huge theoretical breakthrough in computer science, but for end users this is amazing. I could build a simple web site for e.g. brainstorming ideas, and ask people to add the app to their buddy list. I could broadcast a message from the app, asking for ideas about xyz, and moments later their responses would come straight back into the app. From there it would be trivially simple to split them off, write them to a google spreadsheet etc.etc.<br /><br />What this is doing is putting some really powerful collaboration tools in the hands of people who really don't need to know much about programming at all. Fantastic :-)Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-82822741210495615612009-09-22T16:09:00.002-04:002009-09-22T16:11:06.690-04:00XMPP RocksWhile I was playing with the GWT system, the contents of one of the windows suddenly changed to 'XMPP rocks!'. I assume that Peter had sent a jabber message to the server, and the client has - almost - instantly updated that respective window.<br /><br />I think this is hugely exciting. It makes me think of all sorts of new ways of working with web apps.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7533627706765365857.post-24297130110213915262009-09-22T16:02:00.003-04:002009-09-22T16:09:30.143-04:00Undeclared variables are global in GWTYes, I know this is a statement of the obvious - particularly given that it is really javascript that is executing, but I found it interesting nonetheless.<br /><br />I was looking at the startup method Object >> helloWorld, when I suddenly realised that a number of the variables - that were holding windows - were not declared in the method. I opened a workspace and tried sending them messages. Sure enough, it worked.<br /><br />I am gradually beginning to work out how to play with the system :-)Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-7533627706765365857.post-76032239458170689932009-09-22T15:53:00.002-04:002009-09-22T15:57:03.424-04:00GWT Smalltalk becomes colourfulGWT Smalltalk is moving along in leaps and bounds. It now supports the user creation of multiple class browser windows - pretty useful for coding! - and also setting the css for elements.<br /><br />At the moment one can't save code between browser refreshes, but that is coming soon. The bits I am really waiting for are:<br /><ol><br /><li>the ability to define HTML form and input elements e.g. text boxes</li><br /><li>The link to BigTable, so that I can read and write data</li><br /></ol><br /><br />Couple that with the ability to define the startup method, and we have the beginnings of a really interesting toolUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-91524098542916150812009-09-21T14:19:00.002-04:002009-09-21T14:21:59.088-04:00GWT SmalltalkAnd, all of a sudden, I am back :-)<br /><br />Peter Fisk, who some of you may remember developed the Vista Smalltalk system, is also back. This time he has created a version of Smalltalk that runs in the browser. It looks very promising, particularly because it is designed to integrate with Google Wave.<br /><br />If you are interested, please visit the demo site, which is <a href="http://gwt-smalltalk.appspot.com/">here</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-51367498573291749182008-12-28T12:49:00.002-05:002008-12-28T13:26:57.463-05:00Objective-j versus SeasideI have just spent the last few hours learning about objective-j and the <a href="http://www.cappuccino.org">cappuccino</a> framework. In essence, the guys at 280 North have implemented the OS X Cocoa frameworks, in Javascript. The whole thing is very impressive indeed.<br /><br />However, it has got me thinking about different ways of developing web applications. In the Cappuccino model, the client programming is done in objective-j, and is - essentially - totally separate from the backend system. The client application has no connection with the server language. All that is required is the appropriate set of REST services. This is obviously very different from the Seaside model in which the client application is, almost, a by-product of the Squeak code.<br /><br />But which approach is better? Cappuccino looks like an excellent development framework. A lot of basic OS X code (written in Objective-c) can be run, almost completely unchanged, in objective-j. And, perhaps best of all, the documentation is very good. This is achieved partly through the efforts of 280 North, but also because the Cocoa docs match up very well.<br /><br />On the other hand, Seaside offers much better development tools and a very different way of working. I don't know enough about each approach to really form a conclusion, yet. But, it is nice to be spoilt for choice :-)Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7533627706765365857.post-55298958168703208682008-11-08T09:21:00.002-05:002008-11-08T09:35:33.685-05:00Adding Javascript to seasideThis was posted by Lukas Renggli on the Seaside list, seems like useful stuff for the future.<blockquote><br />Whenever you want to include Javascript verbatim, you can use SUStream>>#on:. Otherwise a Smalltalk String is automatically escaped as a Javascript string.<br /></blockquote>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-76683680374392151952008-10-27T13:05:00.002-04:002008-10-27T16:58:22.875-04:00Developing your applications through the debuggerYesterday, while I was listening to an episode of <a href="http://twit.tv/FLOSS">FLOSS Weekly</a>, Randal said something that caught my attention. He talked about writing unit tests and then running them before you had actually written the code - that much I had heard about before - but he then went on to talk about how you would then fix each of the tests by writing the code in the debugger, and clicking proceed. <br />This struck me as a really interesting way of coding. It's almost like having your office applications built into your to-do list. The to do item becomes the item you are trying to do.<br />I think I am going to experiment with this approach - I still need to understand a bit more about the debugger's capabilities. But what really appeals to me is that one could write almost pseudo code (although I think it is more of a declarative description) of what you want the object to do, and work away - a piece at a time - until it does it.<br />In a way, one could think of this style of programming as gradually removing all the bugs until the code does what you want.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7533627706765365857.post-84591862449176850592008-10-27T13:03:00.004-04:002008-10-27T13:05:02.013-04:00Security 'watch outs' in SeasideThere was an interesting question raised on the Seaside list, today. I have pasted the thread below. Basically, if you share a URL with someone, they can potentially take over your seaside session. There are ways around the problem, but it is important to note for the future.<br /><br />><br />> hey, guys..<br />><br />> one quick question after watching the seaside movie last night..<br />><br />> pretend i have an application like ebay written in seaside..<br />><br />> so, i log into my account..<br />><br />> check my bids..<br />><br />> then, i do a search for something..<br />><br />> during that search, i find something my friend would really like..<br />><br />> so i send the link to my friend..<br />><br />> now.. suppose he immediately clicks it (i sent it over IM..)<br />><br />> does he now have full access to my session, including my account<br />> information?<br /><br />Unless you take action to prevent it, yes. This problem isn't unique<br />to Seaside, of course; any system with session keys in URLs will be<br />have the same problem. You can, of course, configure the session key<br />to be stored in cookies, which eliminates the problem. Or you can use<br />a WASessionProtector to prevent the IP address of the user from<br />changing.<br /><br />Note that in either case, you would need to make sure to include<br />enough information in the URL via #updateUrl: that a new session could<br />be built pointing to the right item.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-41746449559867301752008-10-24T09:04:00.002-04:002008-10-24T09:05:40.338-04:00I have no idea what this means, but I hope, in time, it will make senseI am noting it here for future reference.<br /><blockquote><br />> is there a way to clean up the callback registry, or to unregister some<br />> callbacks?<br /><br />With the model of Seaside, it is hard to tell what callbacks are still<br />used when doing AJAX. Therefore I suggest to do a full refresh from<br />time to time.<br /><br />Note that you can easily do a full refresh through AJAX. Just trigger<br />an AJAX request to a normal callback, extract the string between<br />body and /body and place it into the DOM tree. This recreates all<br />the callbacks in the page and ensures that old ones eventually expire.<br />To the outside this "full request" feels like a normal AJAX action,<br />just that it is maybe a bit slower than the other ones.<br /><br />Actually I planned to write a blog entry about this technique, just<br />didn't find the time yet.<br /><br /></blockquote>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-21747348096717692972008-10-23T18:20:00.001-04:002008-10-23T18:23:37.365-04:00So that's what decorators do!I have been reading about decorators in various tutorials, but not really got my head around them - largely because I am still trying to understand more basic information. However, this post in the Seaside list really helps me understand the concept.<br /><br /><blockquote><br /><div id=":y7" class="ArwC7c ckChnd"><br />You may also want to take a look at WADecoration, which can help you<br />to decouple the header/footer from the main page:<br /><br />WADecoration:<br />I am an abstract decoration around instances of WAComponent. I can be<br />added to aComponent by calling #addDecoration: and I change the basic<br />behaviour or look of a component. There are several methods that can<br />be overriden to archive this:<br /><br />- #renderContentOn: to emit xhtml around the decorated component. Call<br />#renderOwnerOn: to let the owner emit its output.<br />- #processChildCallbacks: to intercept the callback processing of the<br />owner.<br />- #handleAnswer: to intercept the answer processing.<br /></div><br /></blockquote><br /><br />I am sure I will find all the methods useful, eventually, but it is the first one that struck me as particularly interesting. It's almost as if it allows you to add 'decoration' to a component. Hmmm, intention revealing method names, not such a bad idea after all ;-)Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7533627706765365857.post-79061463993813523092008-10-23T11:01:00.001-04:002008-10-23T11:02:18.531-04:00Switching between https and http sessionsEstablishing SSL connections is going to be important in a lot of my apps, so <a href="http://code.google.com/p/seaside/issues/detail?id=97">this code snippet</a> from Ramon is well worth notingUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-54835051394446781512008-10-14T13:12:00.003-04:002008-10-14T14:07:37.999-04:00It won't work, if you don't use the right objectsI had a very interesting problem yesterday. I am slowly moving forward on building the threaded discussion system. I have worked out how to render the basic HTML, as a series of components, and I was at the stage of wanting to render the discussion items. My question was how to represent them?<br /><br />In an <a href="http://learningsmalltalk.blogspot.com/2008/08/more-words-of-wisdom-from-joy-of.html">earlier post</a> I had looked at how one might identify the objects in a system, and in particular which ones should be written from scratch. The basic idea was that if one were storing information that already 'fitted' into a class, there was no reason to create something new. The class could be a simple one, such as Array, or something more complex such as Person. In either case, the basic principle was - don't reinvent the wheel. However, as we will see sometimes reinventing the wheel is the right thing to do!<br /><br />I decided to represent the conversation as an array of nested arrays, e.g.,<br /><blockquote><br />discussion := #(topic1 topic2 (sub-topic2.1 sub-topic2.2) topic3).<br /></blockquote><br />Initially, the structure seemed to work well. It was simple, easy to traverse and didn't involve the creation of any new classes. I was quite pleased with myself for following the design principles. Unfortunately, I soon discovered that rendering the subarrays was a pain. Basically, I want Seaside to create an Ordered List and add the entries as List Items. When it comes across a subarray, it should start another ol tag and add the elements.<br /><br />I played with this problem for a little while, but everything I did seemed ugly, and not very smalltalk. In the end, I asked on the beginners' list and received two interesting replies:<br /><ol><br /><li>Randal suggested using the <a href="http://en.wikipedia.org/wiki/Visitor_pattern">Visitor Pattern</a></li><br /><li>Ramon suggested creating two new objects and using recursion (see below) </li><br /></ol><br />I had never heard of the visitor pattern, but fortunately Wikipedia came to the rescue. AIUI this would involve adding a method to both the array, and the strings/arrays it contains, so that they know how to render themselves. Ramon's code, more directly challenged the way I was storing the discussion threads. He suggested something like this:<br /><blockquote><br />renderPost: aPost on: html<br /> html render: aPost.<br /> aPost comments do:<br /> [ :each | self renderComment: each on: html ]<br /><br />renderComment: aComment on: html<br /> html html: aComment body.<br /> aComment comments do:<br /> [ :each | self renderComment: each on: html ]<br /></blockquote><br />For the time being, I am going to try Ramon's approach, purely because I have a better understanding of how to do it. However, I am now intrigued by the visitor pattern, so I will go back to that, once I understand a bit more about OO design. However, for me, the most interesting aspect of this whole problem was the question of why couldn't I see the answer? I think the explanation is that once I had decided to go with an Array, my thinking was limited to that set of methods etc. And, the choice of the Array was driven by the fact that the data <i>could</i> be made to fit into it. So, I now need to develop a more sophisticated design heuristic when thinking about object modelling. Basically, just because something could fit, doesn't mean it should. Now, obviously, design is an iterative process, and all programmers run around refactoring, sooner or later. What I am trying to understand is how I might think about the problem in a more flexible manner.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7533627706765365857.post-58870173916081486002008-10-13T17:07:00.002-04:002008-10-13T17:34:15.664-04:00Creating a framework on top of SeasideNow that I am starting to understand Seaside (and Squeak), I am beginning to realise that I will probably need to customise a bit. Not because of shortcomings, but rather because there will be various good practices that one will almost always want to build into a project. My previous post about Ramon Leon's initialisation tricks is a good case in point.<br /><br />Randal's comment on that post - I have included his version in this post - came at the exact moment I happened to be reading another of his entries, which addressed configuring the startup/shutdown issue. So, my default application settings will now contain something like this:<br /><br /><blockquote><br />MyClass class >> initialize<br /> self registerAsApplication: #foo.<br />Smalltalk addToStartUpList: self.<br />Smalltalk addToShutDownList: self.<br />self startUp.<br /><br />MyClass class >> #registerAsApplication: name<br /> ^(super registerAsApplication: name)<br /> libraries add: SULibrary;<br /> preferenceAt: #sessionClass put: FooSession;<br /> yourself.<br /><br />MyClass class >> startUp<br /> self start. "in case I want more things here"<br /><br />MyClass class >> start<br /><br /> WAKom default.<br /> ... other stuff if I want it...<br /> HttpService startOn: 9090 named: 'httpd'.<br /><br /> MyClass class >> shutDown<br /><br /> self stop.<br /><br /> MyClass class >> stop<br /><br /> HttpService allInstancesDo: [:each | each stop. each unregister].<br /><br /></blockquote>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-39262339517261886062008-10-13T15:31:00.002-04:002008-10-13T15:43:47.350-04:00Tips and tricks for making seaside applications easy to manageOne of my current web applications is built on top of Lotus Domino. I have used Domino & Notes for years, and I have a deep respect for it. This particular application was only meant to have a short shelf life, but it has turned into the application that wouldn't die. Normally, I would be happy with that, it is always nice to know that your work is appreciated. However, in this case, because it was put together in a hurry, we didn't build a web based admin console for it. Unfortunately, for us, this means that every time someone want's to use the app, we have to scurry around with a copy of Lotus Notes, messing about with environment variables by hand. <br />Granted, our 'suffering' is trivial in comparison with people who deal 'real' jobs. After all, as many of my friends have pointed out, all we do is sit around, drinking tea and chatting with people, followed by messing around with computers - hard to argue with that assessment. Anyway, as we move applications over to Seaside, I am really keen that we should do everything possible to simplify the admin. And, that is why I found this section of Ramon Leon's <a href="http://onsmalltalk.com/programming/smalltalk/terse-guide-to-seaside/">Terse Guide to Seaside</a>, so interesting. He wrote:<br /><blockquote><br /><pre>FooComponent class>>initialize<br /> "self initialize"<br /> | app |<br /> app := self registerAsApplication: #foo.<br /> app libraries add: SULibrary.<br /> app preferenceAt: #sessionClass put: FooSession<br /></pre> <p>This sets up a dispatcher at /seaside/foo with the Scriptaculous library (SULibrary) and a custom session class that might contain things like the current user or current database session. You can then highlight the comment “self initialize” and run it to create your site. This has the additional advantage of automatically setting up your site in any new image when you load your package into it and also allowing you to programatically recreate your site on demand. This comes in very handy when upgrading to newer versions of Seaside which sometimes require recreating your sites.</p><p></blockquote><br /></p>I think this is going to be very useful for the futureUnknownnoreply@blogger.com2tag:blogger.com,1999:blog-7533627706765365857.post-12716834152064365492008-10-12T19:26:00.004-04:002008-10-12T19:43:50.522-04:00Oh, so when you say 'literal' you really do mean 'literal'!This comes from the 'hard of thinking' category.<br /><br />I was trying to create my 'children' method - necessary when you are rendering subcomponents in seaside. I knew it need to return a collection, and when I looked at an example, it showed:<br /><br /><pre> ^#()</pre><br /><br />In other words, return an empty array. Obviously, it was using the array literal syntax. This, of course, it where my thinking went horribly wrong. I created my method with the following code:<br /><br /><pre> ^#(pageHeader pageFooter).</pre><br /><br />Seaside stopped working :-( It complained about a decorator method not being understood by ByteSymbol. If you are new to seaside, and you don't already know the answer, see if you can work out what I was doing wrong.<br /><br />Give up? OK, the array literal syntax creates an array of literals. I know, who would have thought it! My array contained the symbols #pageHeader and #pageFooter, NOT the value of those two instance variables. Totally obvious now, but I share it in case you are ever tempted into similar thinking. And, just for your information, the correct code is:<br /><br /><pre> Array with: pageHeader with: pageFooter.<br /><br /><br />## Update: Randal has just pointed out that there is also 'curly brace' runtime Array constructor that was limited to Squeak, but is now available in Gemstone and possibly VW. The syntax is:<br /><br /><pre> {pageHeader. pageFooter}</pre><br /><br />This makes much more sense, and is a very slick way of creating arrays. Thanks Randal<br /></pre>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7533627706765365857.post-42205737006440326732008-10-11T18:44:00.003-04:002008-10-11T18:59:02.180-04:00As Homer would say "Mmmm Smalltalk, is there nothing it can't do?"No sooner had I posted my vague 'pipe dream' about automatically creating methods, than Randal posted a comment, showing exactly how to do it. In case you aren't subscribed to the comments feed, this is what he wrote:<br /><blockquote><br />#(one two three four five) do: [:each | YourClass compile: (each asString , ' self flag: #toBeWritten') ].<br /></blockquote><br /><br />Actually, he finished his code with a :-) . Out of curiosity, and powered by my new found belief that Smalltalk really can do anything, I opened a method finder to check whether :-) is a method. Sadly, and not surprisingly, it is invalid syntax. However, if I ever do find a way of implementing it, I shall get it to return an Anchor tag to this video.<br /><br /><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/B12WBTFLK0Q&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/B12WBTFLK0Q&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-14776532969169536422008-10-11T18:12:00.002-04:002008-10-11T18:27:27.829-04:00Misusing the 'create accessors' menu optionI spent some of last night sketching out the UML for my test project. I wanted to turn the sketches into code, but it was late and I couldn't be bothered to type out all the method names etc. Then I had an idea. If I created instance variables for each of the methods, I could use the Accessor menu item to automatically build the stubs. Then, delete the superflous variables, and my structure is ready to fill in.<br /><br />Now, clearly this is an ugly hack. However, it did save me some time, and it made me curious about how the accessor code generator works. At some point in the future, I will see if I can find the appropriate methods and create a new version. Ideally, I would like to have a new item in class definition, something like stubMethods: that would allow me to generate the methods and mark each one with a self flag: #toBeWritten. call.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7533627706765365857.post-70530579480472728282008-10-11T18:02:00.002-04:002008-10-11T18:12:15.154-04:00Starting to use the refactoring tools in OBUp to now, the only OmniBrowser tool I have used is the 'accessors' option, which automatically generates instance variable access methods. All my other actions, e.g. moving methods, creating subclasses etc., have been done manually, largely because my mind was fully occupied just trying to work out what I was meant to be doing!<br /><br />Last night, I decided to bite the bullet and explore a bit further. And finally, I am beginning to understand why experienced Smalltalkers describe the system as being more than just a language. There are some really clever tools that can save you from, not just wasting time, but also the chance of messing things up, badly!<br /><br />For example, I needed to rename a variable in a method, and therefore also rename its accessor. When I used the rename menu option, it went off, did the rename and then updated all the methods which accessed that method - brilliant!<br /><br />Now, clearly this sort of global search and replace isn't rocket science, but the fact that the tools are so beautifully integrated means that coding, and refactoring, become a 'relative' pleasure.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-19463309895899720332008-10-11T16:14:00.002-04:002008-10-11T16:23:46.140-04:00Smalltalk and EtoileSome time ago I stumbled across an open source project called <a href="http://etoileos.com/">Etoile</a><br /><br />The project is attempting to create a new, configurable, interface for computers, based upon the GNUStep library. My interest lay in the potential to build workspaces that might support creative problem solving. Anyway, recently, they announced that they were planning to build Smalltalk into the system, and that has now happened.<br /><br />The class library is a little unusual, because it builds on top of the GNUStep library, but the basic language will be familar to anyone who has used Smalltalk. I really like the idea of being able to program the whole OS via Smalltalk.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-75949277443690310482008-10-10T20:46:00.003-04:002008-10-10T20:51:22.503-04:00A terse guide to seasideRamon Leon has put together a very good, and - as the name suggests - brief guide to Seaside. You can read it <a href="http://onsmalltalk.com/programming/smalltalk/terse-guide-to-seaside/">here</a>.<br /><br />What I find so interesting about the guide is that a few months ago the contents would have been largely unintelligible to me, and now, they seem to make perfect sense. I am sure people have the same experience when learning any new skill, but it does reinforce the idea that it is worth going back over tutorials, several times, because you can get a lot of new information that you may have missed the first time throughUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-56619762762116493942008-10-06T10:48:00.002-04:002008-10-06T10:50:46.592-04:00Class side variables, an alternative to Global variablesI have built my small experiment, using Globals, and it actually works quite well. However, over the weekend, I was thinking about whether I should use a Class instead of the Globals. Mark Volkmann was thinking similar thoughts, but with a different objective. He added this to the beginners' list<br /><br /><blockquote><br />create a class that represents the enumerated type<br />add a class variable for each enumerated value (must start uppercase)<br />add a class-side initialize method that creates an instance of the<br />class for each enumerated value using basicNew and assigns it the<br />corresponding class variable<br />prevent creation of additional instances by overiding the class method<br />new with "self error: 'new instances cannot be created'"<br />add class-side getter method for each enumerated value that simply<br />returns it<br />Here's an example ColorEnum class.<br /><br />Object subclass: #ColorEnum<br /> instanceVariableNames: ''<br /> classVariableNames: 'Blue Green Red'<br /> poolDictionaries: ''<br /> category: 'SomeCategory'<br /><br />initialize<br /> Red := self basicNew.<br /> Green := self basicNew.<br /> Blue := self basicNew<br /><br />new<br /> self error: 'new instances cannot be created'<br /><br />red<br /> ^Red<br /><br />green<br /> ^Green<br /><br />blue<br /> ^Blue<br /><br />---<br />Mark Volkmann<br /><br /></blockquote>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-63090691829976621862008-10-03T17:35:00.004-04:002008-10-03T17:48:09.292-04:00Timing execution speedPremature optimisation is Evil. However, I think Evil has an unfair reputation. And, because of that, this particular code fragment is well worth remembering<br /><br />Time millisecondsToRun: [].<br /><br />Update: Turns out you can actually send <br /><br />timeToRun to any block. Much easier.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7533627706765365857.post-2014683359301938042008-10-03T17:13:00.002-04:002008-10-03T17:18:37.620-04:00Creating some sort of data busHow might I get the various Seaside components to know about their underlying models?<br /><br />I am trying to build a simple application - sort of a discussion forum. There could be several fora, plus a collection of users - each of whom needs to authenticate. What I am trying to get straight is the easiest/best/most reuseable etc., way of linking the presentation with the data.<br /><br />Clearly, when I instantiate components, I could pass them the address of the model - or just the subpart of the model they will be interested in, but somehow that feels clunky to me.<br /><br />As I was sitting here, thinking about it, it suddenly occurred to me that I could identify the shared objects, e.g., user directory etc, and declare them as Global variables in the Smalltalk SystemDictionary. That way, they would be naturally accessible to all components. But, is this a good idea? Aren't Global variables evil?<br /><br />I don't know, but it does seem to be a neat solution, that builds on top of Smalltalk's 'natural' behaviour, and means that the objects can initialize themselves.<br /><br />I am going to have a play with the design and see how it pans out.Unknownnoreply@blogger.com0