tag:blogger.com,1999:blog-32631630411572045812009-05-03T00:03:22.169+01:00optiludeAbout Martin Aspeli (aka optilude), Plone, music and more.Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.comBlogger19125tag:blogger.com,1999:blog-3263163041157204581.post-56308604340584843692006-11-06T13:30:00.000Z2006-11-06T14:08:01.584ZImproving Plone's third party products storyWe've had a lot of discussions recently about quality management of <a href="http://plone.org/products">plone.org/products</a> - how do people who don't spend their days on plone-user and #plone work out what products are worth betting on, where they are going and whether they'll stay viable in the future?<br /><br />A lot of really great ideas came out of the session we held at the Plone Conference. We've taken the ones that seemed most workable and turned them into a todo-list for the PloneSoftwareCenter.<br /><br />To deliver these ideas, we need volunteers - Archetypes programmers, documentation writers, product reviewers and project manager types.<br /><br />If you want to help out, please check out the OpenPlans collaboration site - add your name and thoughts to the wiki, join the mailing list, discuss, commit code!<br /><br />See: <a href="http://www.openplans.org/projects/plone-products">http://www.openplans.org/projects/plone-products</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-5630860434058484369?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com26tag:blogger.com,1999:blog-3263163041157204581.post-30207937277073803012006-10-06T12:26:00.000+01:002006-10-06T17:43:54.939+01:00The mile high stackSince getting back into doing some Java/J2EE web development, I'm constantly struck by the sheer number of mega-frameworks that I feel I probably should know. It's overwhelming, it gives me a nervous twitch, like I could be investing lots of time in some framework that turns out to be inferior because I have no way of comprehending what else is out there.<br /><br /><blockquote>How do Java web app developers ever get anything done?</blockquote>Here's a list of frameworks and APIs that I've come across in my current project, all of which could have some relevance to my project:<br /><ol><li>Java Servlet API</li><li>JSP syntax</li><li>JSTL</li><li>JSF<br /></li><li>MyFaces/Tomahawk JSF components</li><li>Oracle ADF JSF components</li><li>Java Facelets</li><li>Hibernate</li><li>iBATIS</li><li>EJB 2</li><li>EJB 3</li><li>JBoss SEAM</li><li>Spring</li><li>Struts</li><li>WebWork</li><li>SiteMesh</li><li>Tapestry<br /></li><li>AppFuse</li><li>Log4J<br /></li><li>JUnit</li><li>JMock</li><li>JDBC</li><li>DBUnit</li><li>Cactus<br /></li><li>Maven</li><li>Cargo</li><li>Ant</li><li>Tomcat</li><li>JBoss</li><li>Eclipse</li><li>MyEclipse</li></ol>Oh ... and I need to determine which ones of these can work together, and which of my tools will tolerate which technologies. Aaaaah!<br /><br />To be clear, my application is basically just forms that drive SQL queries. I don't even care so much about security. However, a goal was to try and use best-practice patterns and technologies, to ensure the application could scale up in the future.<br /><br />Now, I'm pretty good developer, I know Java (the language) well and I learn quickly. But several of the pieces above would take me a week or more (each) to learn properly. Obviously some are easier than others, and many are directly competing. But how do I know what to choose? How do I know where to invest my time?<br /><br />I looked for books, but it seems that many of them are out of date by the time they hit the printers. In the blogsphere, there are people who seem to be able to pick and choose between all of these. Power to them, but there is not a great consensus on what is best this week.<br /><br />If there is some canonical book that covers an end-to-end process with best practices - please, I'd like to know. :)<br /><br />But I started thinking about how this works in the Plone community. Im sure new users feel a bit overwhelemed, and that we could do things to make it easier for them. However, based on own experiences from when I first played with Plone, it wasn't nearly so bad:<br /><ul><li>Plone is there, you can touch it and feel it and play with things to see how they break.</li><li>Python is terse and readable.</li><li>Although Java kicks our ass on API docs, it's easier to follow the actual code since the .py files are all there and legible.</li><li>I learn best by example. Like most people, I started with a few copies of some page templates and later some Archetypes classes. That meant I could get results very quickly.</li><li>Plone let me worry about my application and not think about security, user management, URL dispatch etc.</li></ul>Of course, I'm comparing apples to oranges here. Plone is a CMS and a platform for CMS-like systems. J2EE is much wider in scope. However, my application is not so unique - I need forms, page flow logic and database queries. Maybe one day some CRUD logic, and a few pages of text.<br /><br />Obviously, this is all in the terriotory of that infamous Better Web App video, and the cliche exodus of Java coders to Ruby-on-Rails. Fair enough, but I'd like to think that it's not impossible to be productive and feel in control of a Java-based solution. This is often a question of skills (people learn Java in school), of prior investment (people have been trained in Java already), of back-end systems (that already run in Java), and of trust (for business-critical components that may feasibly need a web front-end). I refuse to believe that just because Java is strongly typed and compiled, this can't be done right. So most likely I just haven't discovered that framework yet.<br /><br />However, there is another argument - Java is great for the middle tier, but less productive for the front end. Perhaps we should put more time into finding a bearable way of defining service layers that would let you build your user management and GUI in Plone or Django or Rails and let actual business processes take place in Java beans or EJBs. At least I think that separation would make a lot of decision makers more comfortable - Hibernate, EJB, Oracle (or Postgres) on the back-end, sexy GUI app on the front end that is infinitely more dispsable and lower risk, and is more likely to be what users want if it is written in a framework that encourages agile and rapid development. It may even help to ensure that the middle/back-end business objects are completely decoupled from the GUI and facilitate SOA.<br /><br />Pipe dreams. Anyone got a good Java book to recommend?<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-3020793727707380301?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com16tag:blogger.com,1999:blog-3263163041157204581.post-21889659680732184902006-10-04T10:55:00.000+01:002006-10-04T17:52:53.117+01:00Ignorance and Java Server FacesI'm not quite sure why it's called Java Server Faces - perhaps beacuse it makes my server a two-faced liar - but they're here. Specifically, we're using JSF with Tomcat and Apache MyFaces and whatever versions of the JSF API that Maven decided to pull down today (I think we're on 1.1).<br /><br />Now, I don't have the time to read a few books on the subject, so I'm feeling a bit ignorant and inadequate. That feeling, however, is amplified many-fold by the fact that I am unable to step through most of the code that's not behaving the way I expected. Perhaps I could get there by downloading big tarballs and configuring source attachments in Eclipse, but I worry this may be a big black hole and I'm reluctant. The balance of JAR files being managed in my IDE and deployed in various cases is already quite precarious, so I don't want to upset it.<br /><br />The second thing I miss desperately is pdb's (the python debugger) interactive prompt. Some things are definitely not working the way I expect. I can get some way with the Eclipse debugger and watch expressions, but it's cumbersome and slow.<br /><br />Thirdly, my productivity is hampered by the constant re-compiles. Every time I change something, even a template, I'm recompiling and re-deploying to my local Tomcat instance. It's possible that I could find a way to edit templates in-place in the exploded .war file in Tomcat, or hot-replace them at least, but the only way I knew to do that was with MyEclipse and it doesn't like my Java Facelets templates.<br /><br />This is not made better by the fact that we have three dependent projects. I have to a dance in Eclipse and Maven that involves 'mvn clean install' on a dependent project, cleaning code in Eclipse, and then re-deploying the project. I just lost nearly an hour pulling my hair out writing banal tests when it turned out that Tomcat wasn't executing the code that was being shown in my debugger. Meanwhile, this blog post has formed whilst I'm waiting for things to re-compile. Each time, my distraction period grows a bit longer, and my productivity dips a bit further.<br /><br />Lastly (for now) there is way, way too much magic going on with JSF components. As far as I can tell, every form button is actually managed by a generated snippet of inline JavaScript. This (or something else) is managing some state that persists across Tomcat restarts, which sometimes is persisting the component tree (i.e. the tree of JSF components, which is formed by XML tags in various nanespaces, interleaved in non-obvious ways with the DOM of page itself). Sometimes, I get bizarre errors because some remnant of the page from half an hour ago is still being processed. Sometimes, not reliably reproduceable. The only way I've found to reliably test my code is to close down my browser completely and then re-open it after each re-compile/server re-start. Joy.<br /><br />Further, sometimes the state appears to be saved but it's not - when I click a certain button which has a client-side handler (which is hooked up to a method on a bean by way of some magic expressions) but which aims to stay at the current page after processing, the UI shows form controls with values still entered, but they are magically lost when I click another form button causing an empty form to be submitted. Oh - and sometimes the first command link (think an &lt;a&gt; tag, except it's actually handled with some inline JavaScript on an onclick event and bound into the JSF dispatch machinery) that I click immediately after the application is started leads to a blank page being rendered (something about a phase of the component tree rendering not being ready, I read somewhere), and I have to re-load it to see anything.<br /><br />I'm sure I'm just ignorant and that there are better ways of going about all of this, but I've spent as much time as I can afford with books and Google, and now I just need to get some work done. I'm patching together working practices that feel inferior and clumsy, but basically work. Luckily, this application is small, so there's not that much to do. But it doesn't feel particularly elegant. (/me wants a view and a few adapters)<br /><br />Please refrain from pointing and laughing, but if you have some useful tips, I'm all ears.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-2188965968073218490?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com8tag:blogger.com,1999:blog-3263163041157204581.post-24511896527243559312006-09-25T16:19:00.000+01:002006-09-25T16:33:20.338+01:00Programming aestheticsI really should know better than to post this. Really. Please, don't start a big flame war. But, I peer over the fence from time to time skim through some tutorials and demos on Ruby and Ruby-on-Rails in particular, and one of the things that puts me off it (aside from the sunk cost of my Python knowledge and the fact that my favourite open source CMS project uses Python), is that ... it's so ... ugly.<br /><br />I have an in-built aversion to blocks that end with an <span style="font-style: italic;">end</span> keyword. Call it prejudice. I once learnt Visual Basic. Maybe that's it, but there are also lots of strange symbols flying about. $`? < for inherits-from? Functions without braces (oh, that's just crazy...).<br /><br />If someone has seen the beauty in Ruby, please enlighten me. I genuinely believe that code asthetics are important in motivating programmers, ensuring consistency, catching mistakes and ultimately producing better software.<br /><br />Of course this is totally subjective. But some good examplse of elegance and aesthetics would be nice.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-2451189652724355931?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com5tag:blogger.com,1999:blog-3263163041157204581.post-67797393947477588872006-09-24T18:12:00.000+01:002006-09-24T18:29:37.234+01:00Tool or languageOne of the interesting fallouts from the recent discussions about Nuxeo moving CPS over to Java in the future, is whether relying on tools like IDEs is legitimate, and indeed whether this is just excuse-making for the deficiencies of a language.<br /><br />I'd argue that it doesn't matter. Whether you call it a language or a tool is largely moot. We don't edit Python in ed, we use vim or Emacs or TextMate (sensible people use the latter). Some languages are complemented well by tools, others have less need for them, and some just don't have very good tools available. The important metric is how efficient you are within your working environment, taken as a whole to include your language, your framework and your full toolchain.<br /><br />Therefore, <span style="font-style: italic;">the learning curve = the language + the tool</span>. If getting the tools set up is going to take you a long time, you lose productivity. Eclipse is fairly easy going. Some of the plug-ins are a pain to get and install, others are a breeze. But move down one level, and it can become a pain to manage builds with Maven (which is very powerful but can also be very complex when you step outside the box a little) or Ant (which is not that complicated, but requires a fair bit of manual work). I know companies that invest two weeks of a team's time just to get the build environment set up and configured right, which surely is wrong.<br /><br />And secondly - when the tool does the wrong thing, you probably still need to understand what's going on. That complexity that the tool was hiding is rarely hidden completely, forever, because at some point your tool doesn't yet support the thing you need to do. And in many cases, the tool then expects to manage your source code in its own way and either stomps on your changes or breaks utterly.<br /><br />Good tool design, it seems, is not much easier than good language design. There are still some things I miss in my current, very minimal Python set-up (consisting of Python, Terminal.app, TextMate, Firefox, FireBug), such as code-completion and support for refactoring by finding and modifying code that needs changing because I renamed a function or moved it up or down the inheritance hierachy. But in most cases, Python is high-level enough that the tools I need are in the language itself, saving me from having to learn a whole new tool.<br /><br />And in the meantime, I just love doing this:<br /><blockquote>$ cd Products<br />$ mate CMFPlone CMFCore CMFDefault ATContentTypes<br /></blockquote>This opens TextMate with all those directories in a project, and I can grep (Cmd+Shift+F), edit, read, svn (Ctrl+Shift+A), add and remove files and do everything else I need. The alternative is to start Eclipse, find the right workspace, and add the particular folder to a project (or open an existing one). Thanks, but by the time Eclipse has loaded, I'm already onto my next task. :)<br /><blockquote></blockquote><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-6779739394747758887?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com4tag:blogger.com,1999:blog-3263163041157204581.post-53289040199687879702006-09-21T18:07:00.000+01:002006-09-21T18:37:55.075+01:00Nuxeo 5 - J2EE returnsI'm going to argue out of ignorance. I am not nearly as close to the Nuxeo guys as I am to many other Zope people, and I don't have very much direct experience with CPS at all. However, I want to speculate a bit about the recent announcement that Nuxeo 5 (which is basically the evolution from CPS 4) will be 100% J2EE, in light of some realities that are abundantly clear at my existing employer.<br /><br />CPS always felt a bit reclusive in the Zope world. Florent, Leonnart, Jean-Marc and Tariq (I probably spelled half of those wrong) were visible in the Zope 2, CMF and Five spheres, and I really like them and their work. However, CPS itself was (is) one of things that we often thought, "oh, it's really powerful and good" but never really used. Maybe it's because I don't speak French. Maybe it's because I'm addicted to the Plone community. But CPS was (is) Nuxeo's baby and business model. Which is perfectly, perfectly fine (and it's still fully open source, as will Nuxeo 5 be). Florent and Leonnart in particular contributed tons to CMF, Five and other parts of the stack. But it's these contributions we'll miss (presuming they stop, which I hope they don't), not the CPS-specific Zope technology that we never much re-used (or got around to looking at, perhaps).<br /><br />I've been doing some J2EE work lately. There are things that are quite good about it, and there are things that are not. The Nuxeo 5 FAQ says that Java can be pleasurable with the right tool support. Maybe, but I can count on all my hands and toes the number of hours I've lost to trying to get the build system to play ball, configuring various tools and plug-ins, and debugging strange errors in non-readable code. I'm sure it'd be much better if I worked with Java day in, day out, got tons of training and had it all laid out for me by a standard build that some soul had spent months setting up and testing. At my employer, that'll never be the reality.<br /><br />I have some particular beef with JSF (Java Server Faces). It may be the best Java's got for web UI, but it's still painfully slow and often unpredictable (I see some component tree state caches that don't invalidate properly, for example). It does not play well with JSP at all. Java Facelets help, and even have METAL-style macros, but don't even think of showing a complex JSF-based UI to a web designer. It's hard to know where the line between HTML and JSF components go, and JSF components still involve writing HTML to an output stream with Java code (they say they're working on it). I'm sure I just don't understand it, but I have seen supposedly cutting-edge JSF work (in Alfresco), and it's still awkard (single templates having a myriad of responsibilities).<br /><br />The reason that I don't understand it because the stack is a mile high. JSF builds on JSP builds on servlets builds on streams builds on ... EJBs are just scary. Hibernate is quite good, actually, but I found it hard to debug. I'm quite quick at picking up new technologies, but the amount of technologies I have to understand to be productive is so large. I really wanted to use Spring, but that was another book to read. Again, if I did it day in day out and could affort to take a month on a training course or two, I'd probably do fine, but it's not the reality.<br /><br />Will Nuxeo's programmers be happier with Java? Perhaps so, it may fit their brains well. They may find that it pays back in terms of stability, predictability and scalability (I'm somewhat sceptical of those arguments). They will certainly find it easier to hire new, talented developers. <br /><br />But I can't help suspect that this has a lot to do with commercial realities. Alfresco has created a lot of noise off a product that's very, very impressive on paper and reasonably impressive on screen. It doesn't have anywhere near Plone's customisation/application-building story, for example. But if you read the spec list, it includes things like JSR170 and JSR168. Java standards (supposedly) for content storage and portlets, respectively. It talks to Lucene and Hibernate and MyFaces and MySQL, it uses Spring. These are things that are often singled out as "best-of-breed" open source components.<br /><br />A digression... the Open Source in Java Enterprise world is bit of a parallel universe to the one we know in Zope and Plone. Different kinds of people hang out there. Investment comes from heavy-weights and Sun specification working groups. Apache/Jakarta are kings (and they have a lot of very, very impressive software)... end digession...<br /><br />But Gartner goes out and says, "demand JSR170 to avoid lock-in". The ZODB makes IT managers quiver (call it an object store, not a database, Matt Hammilton says). Butler says, "demand JSR168 to integrate your applications with your portal server". IBM tell you, maybe it'll even work. We have viewlets and component architectures that make those things seem like last year's fashion, but that isn't what people buying IT look for. And probably for good reason. They shouldn't invest their money in unproven solutions, hard-to-integrate platforms or dying products. It's often a lot of money on the table, and being conservative is often a good thing (whether they always get what the bought is another story).<br /><br />So, for Nuxeo, I'm sure that their clients will be very much more impressed if the 10 minute PowerPoint sales pitch includes a number of technologies they have heard about. It makes a lot of sense, especially since their stated target is the ECM sphere, and I'm guessing their customers have a lot of similar Java technologies already deployed. And I am really glad that there will be a credible alternative to Alfresco in the Java-based ECM/DMS market.<br /><br />As far as Plone is concerned, I think our edge will always be in flexibility and agility. I can do things with Plone much faster than I can with any other platform, and I can develop cleaner, better-tested components using Zope 3 technologies than any other platform I've ever seen. At the same time, people like Enfold are doing incredible things with integration, and Plone 3.0 should put us back on the innovation curve with exciting new tools and technologies. Mostly, I'm not worried because the Plone community is so vibrant, with so many cool people and such a lot of friendship. In open source, this is worth more than technology.<br /><br />But at the same time, I'm very eager to find out what Nuxeo's very talented developers will manage to come up with. Hopefully, I'll have a chance to sit down with them over a drink and get their experiences straight from the horse's mouth. Nuxeo.com/org have a commercial story to tell. I wish them the best of luck.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-5328904019968787970?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com3tag:blogger.com,1999:blog-3263163041157204581.post-81565525941886558592006-09-11T08:41:00.000+01:002006-09-11T08:58:51.781+01:00Five small TTW debugging tricksSometimes doing debugging through-the-web is unavoidable. Templates are a prime example - I just spent the better part of two hours trying to work out why my use of metal:macro was not playing ball with a Five browser view (hint: understand what macro you're actually calling...). Sometimes I also simply don't know enoug about how something works to write a reliable and more easily debuggable test, and some trial-and-error is needed.<br /><br />A few things can make it more bearable, though:<br /><ol><li>Customise <span style="font-style: italic;">default_error_message</span>. That is, go to <span style="font-style: italic;">portal_skins/plone_templates </span>in the ZMI and customise this template. Remove the call to <span style="font-style: italic;">metal:use-macro="here/main_template/macros/main"</span>.<br /><br />Why? Because rendering Plone's full 404 template takes a few seconds on my machine. For some reason, this template has always been dog slow. For debugging, all you care about is the error message. By not referencing <span style="font-style: italic;">main_template</span>, you get a plain-text error message, which renders instantly.<br /><br />While you're at it, change <span style="font-style: italic;">&lt;dd translate="" content="structure err_value"&gt;</span> to <span style="font-style: italic;">&gt;dd translate="" content="err_value"&gt;</span>, removing the <span style="font-style: italic;">structure</span> keyword. This gives you a plain-text error message, which will not hide thing slike <span style="font-style: italic;"><foo></foo></span> in when the browser things its HTML.</li><li>Add an external method with a pdb break point. e.g. I have <span style="font-style: italic;">Extensions/debug.py</span>, which contains only:<br /><br /><span style="font-style: italic;">def debug(self):<br /></span> <span style="font-style: italic;">import pdb; pdb.set_trace()<br /><br /><span style="font-style: italic;"></span></span>Then, either in the <span style="font-style: italic;">portal_skins/custom</span> folder or just the root of the Plone site, add an External Method in the ZMI, with name <span style="font-style: italic;">debug-ex</span>, module <span style="font-style: italic;">debug</span>, method <span style="font-style: italic;">debug</span>.<br /><br />With this in place, you can go to <span style="font-style: italic;">http://localhost:8080/Plone/foo/debug-ex</span>. Make sure you run Zope in the foreground (<span style="font-style: italic;">zopectl fg</span>). Your browser will hang, but on the console that you launched Zope, you will get a pdb session, where <span style="font-style: italic;">self</span> refers to the current context (i.e. <span style="font-style: italic;">foo</span> in the URL above).<br /><br />Here, you can do whatever you want, such as inspect the object or mutate it. Remember, you can import other code, call protected methods - do pretty much anything you can do on the interpreter shell. Type <span style="font-style: italic;">pp</span> <span style="font-style: italic;"><name></name></span> to pretty-print a variable or an expression. Type <span style="font-style: italic;">c</span> and press Enter to get your browser back.<br /></li><li>If you're using a Five browser view with a template (either via the <span style="font-style: italic;">template</span> argument to the <span style="font-style: italic;"><browser:page></browser:page></span> ZCML directive or via an explicitly invoked <span style="font-style: italic;">ViewPageTemplateFile</span>/<span style="font-style: italic;">ZopeTwoPageTemplateFile</span>, remember that this does not have security assertions the way .pt files in <span style="font-style: italic;">portal_skins</span> does. That is, you can do things like:<span style="font-style: italic;"><br /><br />tal:content="python:foo._secretVariable.__of__(context).aq_chain"<br /><br /></span>So long as you're in debug mode, the you can reload the page and see the output of that statement. This is quite useful for trying things out and quick-inspecting variables.</li><li>Be ruthless with pdb. Sometimes you are wondering how something works deep inside Zope. So long as you revert your changes afterwards, you can put a pdb statement almost anywhere. For example, whilst debugging a security problem, enable verbose-security in zope.conf and try to put a pdb statement in <span style="font-style: italic;">AccessControl.ImplPython.validate()</span>. You'll have to restart Zope obviously for this to take effect...<br /></li><li>Interleave your work. Sometimes, you need to restart Zope. This is slow. :) Learn to do two things at once, e.g. work on improving tests for other parts of the code, writing new interfaces or updating documentation while Zope is restarting, or go help someone with their problems on <span style="font-style: italic;">#plone</span> on IRC :)<span style="font-style: italic;"><br /></span></li></ol><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-8156552594188655859?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com8tag:blogger.com,1999:blog-3263163041157204581.post-55496453366335204602006-09-06T10:09:00.000+01:002006-09-06T10:48:15.939+01:00Category greedI think it's really, really great that people contribute <a href="http://plone.org/documentation">documentation </a>and <a href="http://plone.org/products">third-party products</a> to Plone and publish them on plone.org. However, as the reviewer of a lot of the submissions, I have one complaint:<br /><br /><span style="font-weight: bold;">Selecting every conceivable category, audience or section makes your content </span><span style="font-style: italic; font-weight: bold;">harder</span><span style="font-weight: bold;"> to find, not easier. </span><br /><br />80% of the items I review have selected four or five audiences (Oh, you know, this is relevant to site administrators, developers, advanced developers and integrators, customisers, maybe), or two or three product categories (hey, there's code here, so let's call it a code example, and also it could go into the misc category, and really, it's a service so let's put it there too).<br /><br />Unfortunately, that just makes the categories less useful to everyone.<br /><br />This is why we have reviewers, but reviewers forget to check the categories (or they make the same mistake) and we end up with cruft. We could change these to a single-select field, but there are cases where we need multiple categories. Perhaps we could introduce a validator that means only reviewers can select more than one category, but this is somewhat clunky.<br /><br />So please - apply some critical judgement. The categories are there to make it easier to browse the content, as the listings are grouped by them. If every grouping has every item, then we may as well just not have categories.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-5549645336633520460?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com7tag:blogger.com,1999:blog-3263163041157204581.post-43687431586952932792006-09-04T10:03:00.000+01:002006-09-04T11:23:22.029+01:00Maybe we're just not that kind of peopleI always enjoy reading Carlos de la Guardia's posts on the stature of Zope and Zope 3 in the Python community. His <a href="http://blog.delaguardia.com.mx/index.php?op=ViewArticle&articleId=63&amp;blogId=1">top ten list</a> hits it on the head, I think.<br /><br />One of the big, big criticism against Zope 3 is that it has no website from which it tries to create buzz. I'm not going to repeat that argument, but look at something like the <a href="http://www.turbogears.org/">competition </a>and you get the <a href="http://zope.org">idea</a>.<br /><br />Then again, Zope has always felt a bit inwardly focused. I don't think its developers feel the need to be validated so strongly by having an influx of people knocking down the doors. They are focused on making the perfect framework, and Zope 3 is in many ways lightyears ahead of the <a href="http://java.sun.com/javaee/">competition</a>. They are people who run small businesses or work for places like Zope Corp or Infrae. They are solving their customer's needs, refactoring ruthlessly and building something they believe in - a framework they love to use, that makes their lives easier (we hope).<br /><br />But they are not website building people. There is a project going on to build a new webiste, and kudos to people like Martijn Fassen and Philipp von Weitershausen for shepherding this along, but it's been months and I'm guessing it will still be months. We're defining IA and web design still. As far as I know, there's not even a consensus on which technology platform to run it on (I have my <a href="http://plone.org">pragmatic preferences</a>, of course, but there are politics to be navigated there as well).<br /><br />In a way, it's a bit of a Catch 22. I think you need a certain type of semi-peripheral enthusiast to build kick-ass websites. Hardcore coders are rarely good web designers or even good at defining information architecture and site structure. More impotantly, they rarely burn to do it, they'd rather be making zope.app a less hostile environment and give us a decent local site customisation story (thank you!).<br /><br />But the kind of bright young things looking to make a name for themselves, who are happy to be drawn into a holy war over their web framework and throw insults at all those who dear imply it's anything but perfect - the perfect guys to make the advocacy website (with some moderation) - are just not Zope 3 users (at least there aren't many of them). For better or for worse...<br /><br />Maybe they would be if there was a better website. But I think it's also true that Zope 3 targets a more "serious" end of the market, with a steeper learning curve, but with more power and elegance. Whomever may read this and think I'm slagging off the people who build websites for Django or TurboGears or Rails - wait with hitting that comment link. I think you guys are doing a great job, and the bit of my heart that's sentimental towards Zope envies you. I just think there's a different type of community behind Zope 3 - unfortunately one that has many fewer people truly interested in doing this kind of work.<br /><br />The other part of the problem is governance. Zope 3 lacks a strong leadership figure to put out edicts about this kind of thing. We have strong leadership figures in the shape of Jim, Stephan, Martijn and Philipp - but these are not people interested in defining how Zope 3 should be marketed, and Jim (who's probably least interested, which is no criticism at all) is probably the only one who has enough legitimacy to be able to say "this is what we must do". Well, Martijn and Philipp are trying, but I'm sure they feel it's a bit of a slow, uphill struggle to gain enough buy-in from the rest of the community to get something done <span style="font-style: italic;">quickly</span>. It is done by committee and consensus, like most things in Zope 3 land, and I'm not quite sure marketing is a job best done that way. The promised land may be the Zope Foundation, but for someone not directly involved with its creation, I'm not seeing much of it.<br /><br />Of course, I may be wrong, and I really don't wish to undermine the efforts of the people who are trying to rectify the situation (I've even offered to help with the <a href="http://plone.org/products/plonesoftwarecenter">technologies</a> I know well that I think <span style="text-decoration: underline;"></span>could <a href="http://plone.org/products/ploneshelpcenter">help)</a>.<br /><br />But, here's a thought - perhaps, the people who care and who would benefit indirectly from Zope 3 gaining more recognition in the wild in terms of more business could pool some resources and <span style="font-style: italic;">pay</span> someone to build the right kind of site?<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-4368743158695293279?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com5tag:blogger.com,1999:blog-3263163041157204581.post-21023789115826561012006-09-01T10:45:00.000+01:002006-09-01T12:11:05.163+01:00Summer of CodeIt's been a couple of weeks since the formal end of Google's Summer of Code programme where the Plone Foundation were represented with three students. On the whole, it has been a success, though there are lessons to be learnt.<br /><br />Right up front, I'd like to say - <span style="font-weight: bold; font-style: italic;">Thank you Google</span>! It's not every day an organisation spends $3m on handouts to the open source world. Plone certainly will feel the benefits of the work that have come out of this for years to come.<br /><br />First - the successes. Hanno Schlichting, mentored by Alec Mitchell, has done some great work on our i18n architecture, that benefits not only Plone, but the CMF and Zope (3) communities as well, and produced a bunch of collateral benefits, such as a GenericSetup syntax for local site setup in Zope 3. I don't think anyone really doubted that Hanno would kick ass, being one of our more consciencious and consistently solid contributors, but it's great to see him rewarded and motivated by the programme. Hanno <a href="http://hannosch.blogspot.com/2006/08/summer-is-over.html">blogged about this progress here</a>.<br /><br />Markus Fuhrer, mentored by me, also made some giant strides. He was working on <a href="http://plone.org/products/plone/roadmap/157">PLIP 157 - Content Rules Engine</a>. To be fair to Markus, he was thrown in rather at the deep end, building a "pure" Zope 3 package at the base to model the use case and a first cut at the Plone UI for it. Unlike Hanno, Markus had no previous Plone experience, and much of this was new to his mentor as well. Moreover, the task was to build a very open-ended framework, taking as much complexity as possible away from people wanting to build new "rule elements" (actions that you can string together to form a rule that is executed upon some event) and plug them into the system. That necessarily put a lot of the complexity in the framework itself.<br /><br />Being an old friend and living in London, we were able to pair-program (with plenty of Falafel and Diet Coke) about once a week. The biggest victory in my eyes is that Markus now has a good understanding of how this architecture works, and it is my sincere hope that he will be able to stay involved with its maintenance and further development. PLIP 157 is currently under review for Plone 3.0. You can check out the <a href="http://svn.plone.org/svn/plone/review/plip157-contentrules/">review bundle</a> for yourself. I also hope that the <span style="font-style: italic;">plone.contentrules</span> package (which has no Zope 2 or Plone dependencies, and thus should work in pure Zope 3 applications as well) will be of use to the wider Zope community.<br /><br />The last student we took on was less forunate. He was tasked with <a href="http://plone.org/products/plone/roadmap/118">PLIP118</a>, refactoring PlonePortlets into a more general and modern (as in, less Archetypes-dependent) solution for managing portlets in Plone. Unfortunately, we never saw any code. I worry that perhaps we scared him away (his task of was similar complexity to Markus'), and he eventually broke communication with us, without producing any code.<br /><br />In the aftermath, I picked up this work with a view to get it ready for the Plone 3.0 review deadline. A huge thank-you to Philipp von Weitershausen for helping me with many of the Zope 3 details, and to Geir, Dorneles and Helge from PloneSolutions and Christof Hammerlie (who was working with us at the Archipelago Sprint), who not only made the original PlonePortlets but helped with use cases and design. You can check out the <a href="http://svn.plone.org/svn/plone/review/plip118-portlets/">review bundle</a> for PLIP 118 if you are interested in how this works. Similarly to <span style="font-style: italic;">plone.contentrules</span>, I'm hopeful that <span style="font-style: italic;">plone.portlets</span> can be useful to the Zope 3 community as a standalone component.<br /><br /><span style="font-weight: bold;">The lessons we learnt</span><br /><br />There are many things to learn from the Summer of Code experience, especially if Plone wishes to participate in the programme should Google run it again. Here area few:<br /><ol><li><span style="font-style: italic;">Plan early! </span>In the days leading up to the deadline for proposals, there was some chaos. I believe we benefit both ourselves and our students the most by having clear proposals with agreed scope for students to pick, and by having well-prepared potential mentors. Internal debates about what is a reasonable scope for an SoC project and what potential projects are more important than other ones should probably happen before applications have to be rated in earnest.<br /></li><li><span style="font-style: italic;">Don't expect too much!</span> We were initially hoping to get about 10 students. That was completely unrealistic. There are many organisations and a few meta-organisations like Apache and GNU who (deservedly) get many more students. Reputation, previous year's experience and relevance to the world at large seemed to be important factors for Google to determine the allocation. And yes, we are smaller than Drupal, say - we have to adjust our expectations accordingly.</li><li><span style="font-style: italic;">Evaluate proposals carefully!</span> It's very hard to evaluate a student based on the short text they submit. The potential mentors pushing for a particular project may also be blinded somewhat by the desire to see that work done.<br /><br />Our three highest rated students ended up being one safe bet (Hanno), one student I could vouch for (Markus) and one unknown that we were hoping to get involved in the community. I personally think that was a decent balance. Hanno deserves recognition for the great work he does, Markus ended up producing something very solid; and getting fresh talent involved is an explicit and important goal, even if there is more risk taking on an unknown.<br /><br />Unfortunately, there were other students <span style="font-style: italic;">marginally</span> below the line (like Tim Hicks, who got as many points as the third student and seemed a victim of chance for being excluded). In fairness to Tim, he probably would have been a safer bet, having already contributed to Plone by way of Quills, Ploneboard and other components. Balancing the risks and benefits of betting on an unknown is important, especially when the number of allocated students is low. Having clear, honest and selfless discussions among the evaluators on the students in question is paramount.<br /></li><li><span style="font-style: italic;">Communicate!</span> One of the problems with the portlets work that got canned was that we never formally kick-started the student. We offered to help, but expected the student to pull more than we'd push. In this case, that didn't happen.<br /><br />The student ran into trouble (such as trying to install Plone 2.5 on Zope 3.0) that we could have avoided if we were more directly aware of what he was doing. I take some self-criticism for being qutie tough on the student in this case, out of frustration that he had spent a lot of time doing something we could have told him would be a dead end - all because we were out of the loop. Unfortunately, the pattern repeated itself with subsequent problems, and communication did not noticably improve.<br /><br />Of course, the communication loop has two ends that need to stay active. Mentors are busy, but have a responsibility towards the student. Different students may need different amount of time invested in them. Furthermore, not every student will be as used to the constant email and IRC communication that we all take for granted. We need to be understanding of this, and help the student get over the initial bumps. We need to be helpful and friendly, and have realistic expectations of how much of a learning curve the student has to climb (and not just in terms of the work, but also just the experience of being part of an open source community).<br /><br />Equally, students have a <span style="font-style: italic;">responsibility</span> to be the more active party. They are being paid a not-insignificant amount of money to do a job (mentors are not paid, mentoring organisations are paid $500 per student, compared to the $4,500 each student receives). It is not something to be taken for granted, and it is expected that the student should be as many hours into this as they would any other summer job. And this is <span style="font-style: italic;">hard</span> - a student (Markus excepted) doesn't have a boss looking over their shoulder when they are blogging instead of working. They have to take significant responsibility for their own planning and be self-managing. They have to be able to ask for help when they are stuck. They have to be able to manage expectations with their mentors and define the scope of what they believe they can acheive. Naturally, some candidates will be better at this than others.</li></ol>On the whole, Summer of Code has been a very enjoyable experience, and I believe a very positive thing for Plone. We are grateful to Google, and grateful to our students and mentors. Hopefully, we'll get to do it all again next year :)<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-2102378911582656101?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com3tag:blogger.com,1999:blog-3263163041157204581.post-54162088994014375502006-08-31T00:39:00.000+01:002006-08-31T00:55:46.750+01:00My new favourite place to put a pdbI'm not sure if this is a good thing. In fact, I'm pretty certain it's a bad thing. But sometimes, using Five views and acqusition hurts. The main problem is that Zope 2 (still) depends on acqusition for security, and our code tends to rely on implicit acquistion (acquiring attributes, tools, templates from portal_skins...) to stitch our application together. Zope 3, on the other hand, doesn't have this kind of implicit acquistion-is-everywhere magic. Which is probably a good thing, but it does make for some awkward marriage of the two in Five sometimes.<br /><br />The basic pattern is, you mix Acquistion.Explicit into your view classes and other objects (or if you have to, Acquistion.Implicit, or sometimes OFS.SimpleItem.SimpleItem... I'm still trying to work out the hard and fast rules, and I'll tell you when I can). You then sometimes have to do some aq-wrapping as well. obj.__of__(aq_inner(self.context)) seems to be a favourite. And quite often you have to do some aq-unwrapping - aq_base() and aq_inner() are your friends.<br /><br />But it's often quite hard to know where the acquistion chains are coming from, and what they are at various stages of traversal. Today, for example, I discovered that if you have a Zope 3 style container (something that provides IItemMapping) traversal will be handled by zope.app.container.traversal.ItemTraverser. This looks like this:<br /><br /> <blockquote> <span style="font-family: courier new;">def publishTraverse(self, request, name):</span><br /><span style="font-family: courier new;"> """See zope.publisher.interfaces.IPublishTraverse"""</span><br /><span style="font-family: courier new;"> try:</span><br /><span style="font-family: courier new;"> return self.context[name]</span><br /><span style="font-family: courier new;"> except KeyError:</span><br /><span style="font-family: courier new;"> view = queryMultiAdapter((self.context, request), name=name)</span><br /><span style="font-family: courier new;"> if view is not None:</span><br /><span style="font-family: courier new;"> return view</span><br /><br /><span style="font-family: courier new;"> raise NotFound(self.context, name, request)</span></blockquote><span style="font-family: courier new;"></span><br /><br />Great. It looks for the given name that you're traversing to in the container, and returns it if it can, otherwise it tries to look it up as a view, which is what you'd expect.<br /><br />The problem, though, is that this view never gets acqusition-wrapped. Thus, the acquisition chain is broken at the view, and it has no appropriate security context, for example. This was giving me incredibly non-debuggable security errors.<br /><br />After some helpful suggestions from Zope 3 + Five guru Philipp von Weitershausen, I decided to put a pdb break point in ZPublisher/BaseRequest.py, specifically the traverseName() function. (This is Zope 2.10, btw, it's different in earlier versions). This gets passed the name ('name') that is being traversed to, and the object ('ob') that is "as far as I've gotten so far". Thus, let's say you're traversing to /plone-site/container/@@myview - it will start out with ob as the Application and name = 'plone-site', then ob as the Plone site and name='container' and so on.<br /><br />Of course, this is a bit annoying, because if it does render a page, it will traverse to tons of resources like images and stylesheets. Therefore, it may be better to put a conditional break point in there, by doing something like:<br /><br /><span style="font-family: courier new;"></span><blockquote><span style="font-family: courier new;"> if 'myview' in name:</span><br /><span style="font-family: courier new;"> import pdb; pdb.set_trace()</span></blockquote><span style="font-family: courier new;"></span><br /><br />It was here I discovered that the view being looked up was not automatically acquistion-wrapped. My custom traverer for my own type looks like this - and it works!<br /><br /> <span style="font-family: courier new;">class PortletAssignmentMappingTraverser(ItemTraverser):</span><br /><span style="font-family: courier new;"> """A traverser for portlet assignment mappings, that is acqusition-aware</span><br /><span style="font-family: courier new;"> """</span><br /><span style="font-family: courier new;"> implements(IBrowserPublisher)</span><br /><span style="font-family: courier new;"> adapts(IPortletAssignmentMapping, IBrowserRequest)</span><br /><span style="font-family: courier new;"> </span><br /><span style="font-family: courier new;"> def publishTraverse(self, request, name):</span><br /><span style="font-family: courier new;"> ob = ItemTraverser.publishTraverse(self, request, name)</span><br /><span style="font-family: courier new;"> return ob.__of__(self.context)</span><br /><br />Now - Philipp has been waving at his plan for world domination - make acquisition less important in cases like this. Dude - we can't wait! :)<br /><br />In the meantime, I hope we can work out the common patterns and document them, at least.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-5416208899401437550?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com0tag:blogger.com,1999:blog-3263163041157204581.post-59515674139457593032006-08-29T16:56:00.000+01:002006-08-29T17:17:25.924+01:00More lame files - __init__.py and browser.pySince having a blog gives me a license to rant...<br /><br />Don't put code in __init__.py files. Imports, sys.modules mangling, deprecation warnings - all fine. But real functionality? Blah... I never look at __init__.py files and I wouldn't expect anyone else to do it in my own code. In <a href="http://www.python.org/dev/peps/pep-3100/">994 years</a> they may even become less important.<br /><br />Secondly - and relatedly, think ahead. If you have only one view now but you may need ten in a week's time, don't create a browser.py for the 'browser' module (which, by Zope 3 convention, is where your browser views and resources tend to live). First of all, you may need a template, which lives best in browser/template.pt. Secondly, most applications or products have several views, and having tons of classes defined in one ever-growing browser.py is a pain. At some point, you'll refactor them into sub-files and get into an import jungle.<br /><br />Of course, if you're creating something that by definition should have only one view (i.e. a piece of infrastructure), then great - dont' clutter it up with unnecessary directories. But if you're building something at the Plone level, like a set of content types, they'll probably have more than one view, and creating a directory isn't going to kill you.<br /><br />Oh - and thirdly.... we shouldn't have called the file for the @@plone view plone.py. Why? Because we now want to have namespaces like plone.portlets. That leads to <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip118-portlets/browser/plone.py">things like this</a>:<br /><pre>IPortletManager = sys.modules['plone.portlets.interfaces'].IPortletManager<br />IPortletManagerRenderer = sys.modules['plone.portlets.interfaces'].IPortletManagerRenderer</pre>Can you figure out why this wouldn't work?<br /><pre>from plone.portlets.interfaces import IPortletManager</pre> Python 2.5 is rumoured to have relative imports ala ZCML which may make this better, but it won't solve all problems.<br /><br />Ah, I feel all better now.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-5951567413945759303?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com6tag:blogger.com,1999:blog-3263163041157204581.post-50009462674137199912006-08-29T12:37:00.000+01:002006-08-29T12:55:46.445+01:00adapters.py - a sure sign that you're not using Zope 3 enough<span style="font-weight: bold; font-style: italic;">edit</span>: heh... Freudean slip - I originally titled this 'annotations.py - ....'<br /><br />There is a kind of worrying (well, perhaps not so worrying, but it does annoy me) precedent being set in a few places:<br /><br /> <span style="font-style: italic;">adapters.py</span><br /><br />In Zope 3, adapters are everywhere. Views are adapters (multi-adapters, in fact). Namespace traveral is done with adapters. Regular traversal is done with adapters. And well-designed Zope 3 code tends to use adapters a lot:<br /><ul><li>One interface for each logical component or piece of functionality</li><li>One or more adapters (or utilities) providing the functionality of a particular interface</li></ul>Of course, some "base" objects, like content objects, are not looked up as adapters and provide some interface directly, but they tend to be the context of adapter lookups for other interfaces.<br /><br />Usually, though, when something is context-dependent, it tends to be an adapter. You adapt a content object to IAnnotations via an annotations-adapter to be able to annotate it. You adapt an object to ISized to work out its size. You adapt an object to ISlapTheMonkey to slap the monkey attached to this particular context.<br /><br />... so why would you put all of them in a single file?<br /><br />That some functionality is provided by an adapter should be a consequence of the design. Logically related functionality should live in the same module (file), and each module should have a clear boundary of responsibility.<br /><br />I guess my point is - adapters are not special. They are just a way to modularise your code and separate concerns. If they excite you so much that you want to keep them on their own little pedestal in adapters.py, that's great (you've been drinking the kool-aid), but if you keep using them, they'll just become a natural part of your toolset and you'll use them all over the place, where they make sense.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-5000946267413719991?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com3tag:blogger.com,1999:blog-3263163041157204581.post-31284260192702013182006-08-24T16:09:00.000+01:002006-08-24T16:17:30.046+01:00Packages, packages, packagesIt seems I'm being reptititve in my blog topics, but in case you don't read the Zope 3 list:<br /><br />Zope Corporation has just released <a href="http://www.nabble.com/New-open-sourced-Zope-Corporation-packages-tf2159153.html">a whole slew of packages for Zope 3</a>, many of which could be very useful to Plone. For example:<br /><ul><li>zc.index -Zope 3 style indexes for RTF, MS Word, HTML etc. (wow...)<br /></li><li>zc.preview - In-browser previews for various file formats<br /></li><li>zc.notification - Framework for doing e.g. email notifications<br /></li><li>zc.selenium - The Zope 3 equivalent of PloneSelenium</li><li>zc.vault - A subversion-style repository stored in the ZODB (wow again)</li><li>zc.winauth - Authentication against Windows domains</li><li>zope.html - FCKEditor Zope 3 widget</li><li>zc.set - Persistent Python set implementation</li></ul>All to be found in <a href="http://svn.zope.org">svn.zope.org</a>. :)<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-3128426019270201318?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com0tag:blogger.com,1999:blog-3263163041157204581.post-13646659158712713642006-08-22T10:44:00.000+01:002006-08-22T12:21:04.881+01:00The things you find...I sometimes nip into <a href="http://svn.zope.org/">svn.zope.org</a> looking for a code example. I'm constantly amazed at what I find there. Here are today's discoveries (note that I'm only skimming READMEs at this point, so apologies if I get some of this wrong).<br /><ul><li>z3c.javascript - Zope 3 resource registrations and registrations with zc.resourcelibrary (if present) for Prototype, MochiKit and friends</li><li>z3c.traverser - Plug-in architecture for making custom traveral adapters. Joy! I believe lovely.tag, for example, uses this to get URLs like /tag/foo to work.<br /></li><li>z3c.zalchemy - Integration with <a href="http://sqlalchemy.org">SQLAlchemy</a><a href="http://beta.blogger.com/sqlalchemy.org/"></a>, a lovely RDBMS and ORM tool. Note that Kapil has been working on somehing called Alchemist that also provides some SQLAlchemy integration for Zope 2/3/Plone.</li><li>z3c.extfile - An external (large) file handling solution.</li></ul>There are lots of other good packages in there as well - zc.table, zc.relationship, zc.catalog... Many of these resonate with things we either are doing or want to do in Plone 3.0 and beyond.<br /><br />Therefore, it's probably wise to add svn.zope.org to the list of places to check before you start building something from scratch that may have been invented before. :)<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-1364665915871271364?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com3tag:blogger.com,1999:blog-3263163041157204581.post-79319133572860272792006-08-21T10:01:00.000+01:002006-08-21T15:05:42.193+01:00Local adapters in Zope 2.10Further to <a href="http://hannosch.blogspot.com/2006/08/we-are-getting-local.html">Hanno's excitement about local components</a>, I thought I'd add something of my own. As Hanno points out, systems like Plone where more than one site (with possibly different configurations) can be in the same Zope instance, and where much of the configuration needs to be done through-the-web, there is often a need for persistent, local components. In CMF, we have tools, which are persistent (in-ZODB) singletons (per site). Their analogue in the Zope 3 world are persistent (local) utilities.<br /><br />In Zope 2.10 (and 3.3), Jim has refactored the component architecture to make it much, much easier to work with local components. Components are registered with a <span style="font-style: italic;">site manager</span>, of which there is a global one (the deafult one use when you register components in ZCML) and any number of nested local ones attached to one or more <span style="font-style: italic;">sites</span>. Hanno has made the Plone site root a site on the 3.0 bundle, which means that we can attach local components to it.<br /><br />Imagine you have an object 'obj' that you want to register as a local utility providing an interface 'iface' with the given name 'name'. Here's how you'd register that as a utility on a particular site:<br /><blockquote style="font-family: courier new;">sm = getSiteManager(site)<br />sm.registerUtility(obj, iface, name)<br /></blockquote><blockquote></blockquote>Hanno has bundled this functionality into a GenericSetup export/import handler <a href="http://dev.plone.org/plone/browser/plone.app.i18n/trunk/plone/app/i18n/exportimport/sitemanager.py">here</a>, which means that setting up local utilities should be as simple as an <a href="http://dev.plone.org/plone/browser/plone.app.i18n/trunk/plone/app/i18n/profiles/default/sitemanager.xml">XML file</a>.<br /><br />After this registration has been made, you can do this:<br /><blockquote style="font-family: courier new;">util = getUtility(iface, name=name)</blockquote>and you should get back 'obj'.<br /><br />That is - if you are in the right context. Upon traversal, Zope (and Five, in our case) will know the context and look up the containment hierarchy to find out where the nearest site manager is. If a site manager does not contain a given component registration, it will fall through to its parent, all the way up to the global site manager. Again, Hanno has taken care of this in Plone. In a <a href="http://dev.plone.org/plone/browser/plone.app.i18n/trunk/plone/app/i18n/locales/tests/test_countries.py">test</a>, you may need to do something like:<br /><span style="font-family:courier new;"></span><blockquote><span style="font-family:courier new;">setHooks()</span><br /><span style="font-family:courier new;">setSite(site)</span><br /></blockquote>To simulate what Zope may otherwise do during acquistion.<br /><br />Now, in <a href="http://svn.plone.org/svn/plone/plone.portlets">plone.portlets</a> I have been doing something similar with local <span style="font-style: italic;">adapters</span>, with no small amount of help from Philipp von Weitershausen. Now, to register a local adapter, you only need to call <span style="font-style: italic;">registerAdapter() </span>on a site manager:<br /><blockquote style="font-family: courier new;">sm.registerAdapter(required=(iface1, iface2,),<br />provided=iface, name=name, factory=callable)<br /></blockquote>Here, 'callable' could be a class or a function that produces the adapter providing 'iface'. It will take two parameters, being passed the objects providing iface1 and iface2.<br /><br />In plone.portlets, however, the pattern is a bit more interesting. The reason for needing a local adapter in the first place is to satisfy <span style="font-style: italic;">zope.contentprovider</span>. This comes with a TALES expression type handler for the <span style="font-style: italic;">provider:</span> expression type. If you write a page template:<br /><blockquote style="font-family: courier new;">tal:replace="structure provider:plone.leftcolumn"</blockquote>zope.contentprovider will look up a multi-adapter providing <span style="font-style: italic;">IContentProvider</span> from (context, request, view) and call its <span style="font-style: italic;">update()</span> and <span style="font-style: italic;">render()</span> methods.<br /><br />In plone.portlets, we want to be able to register a content provider to render the left portlet column in place of this expression, which means that an appropriate adapter lookup must be found. Furthermore, the assignment of portlets to a context is a persistent, site-local concept. This implies that not only must the correct <span style="font-style: italic;">IContentProvider</span> local adapter be located, it must also know which "portlet manager" to query for the list of portlets to render.<br /><br />The solution to this problem is to let the adapter factory (the callable that produces the actual registration) be a persistent object. The implementation of <a href="http://dev.plone.org/plone/browser/plone.portlets/trunk/plone/portlets/manager.py">PortletManager</a> has a <span style="font-style: italic;">__call__()</span> method which can produce the appropriate implementation of <span style="font-style: italic;">IContentProvider</span> in the form of a <span style="font-style: italic;">PortletManagerRenderer</span>. When instantiated, this is told which portlet manager it is rendering.<br /><br />Thus, a portlet manager in <span style="font-style: italic;"><site>/.portlets/left</site></span>, for example, is registered (using <a href="http://dev.plone.org/plone/browser/plone.app.portlets/trunk/plone/app/portlets/exportimport/portlets.py">a GenericSetup handler</a>) <a href="http://dev.plone.org/plone/browser/plone.portlets/trunk/plone/portlets/manager.py"></a>as the adapter factory for the <span style="font-style: italic;">plone.leftcolumn</span> adapter:<br /><blockquote style="font-family: courier new;">sm.registerAdapter(<br /> required=(Interface, IBrowserRequest, IBrowserView,),<br /> provided=IContentProvider, name='plone.leftcolumn',<br /> factory=site['.portlets']['left'])</blockquote>In effect, this achieves a link between the (persistent) adapter registration for the <span style="font-style: italic;">plone.leftcolumn</span> content provider adapter and the (persistent) portlet manager storage.<br /><br />Of course, users of the library shouldn't have to do any more than <a href="http://dev.plone.org/plone/browser/CMFPlone/branches/plip118-portlets/profiles/default/portlets.xml">this</a> in a GenericSetup profile: <span style="font-family:courier new;"></span><span style="font-family:courier new;"></span><br /><blockquote style="font-family: courier new;"><portlets><br /> <portletmanager id="left" column="plone.leftcolumn"><br /></portletmanager></portlets></blockquote><blockquote></blockquote><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-7931913357286027279?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com4tag:blogger.com,1999:blog-3263163041157204581.post-5853002935022092632006-08-18T00:52:00.000+01:002006-08-18T01:24:44.366+01:00Componentising the content menuI have an unstated personal vendetta for Plone 3.0 - make the UI more pluggable. There are a few places where people are forced to do very invasive template overrides because Plone doesn't provide any proper way for them to plug in the UI they want. This in turn makes us dependent upon having certain types of customisations in CMFPlone proper, rather than letting them be managed by add-on components. discouraging certain type of innovation in the wider community.<br /><br />A big part of that will be <span style="font-style: italic;">viewlets</span> - a way of composing snippets into a full page. Alec Mitchell did a ton of great work on making these work in Five, and I'm sure their impact will be felt in very positive way for Plone 3.0.<br /><br />The other one is metadata - how many people would like to be able to apply a standard (perhaps required) field to every content type without having to sub-class every single one of them? At least for Archetypes, a solution is within reach, thanks to some great work by David 'whit' Morriss, which I adapted and used <a href="http://svn.plone.org/svn/collective/borg/trunk/content/schema.py">here</a>. Daniel Nouri, the new Archetypes release manager, is interested in this as well, so with a bit of luck and work, we'll get that one done in time.<br /><br />The last bit is a template with which I'm <a href="http://plone.org/events/sprints/past-sprints/amsterdam/pictures/alecm/image.2005-04-18.9358211149/image_view_fullscreen">rather too familiar</a> -<a href="http://svn.plone.org/svn/plone/CMFPlone/branches/2.5/skins/plone_templates/global_contentmenu.pt"> global_contentmenu</a>. This is the code that controls the green bar with the <span style="font-style: italic;"><span style="font-style: italic;">actions</span></span>, <span style="font-style: italic;">display</span>, <span style="font-style: italic;">add item</span> and <span style="font-style: italic;"><span style="font-style: italic;"></span>state</span> menus.<br /><br />Take a look at the code. This is a prime example of the stuff you should not do with ZPTs. There is more logic in there than in pretty much any other page template, it's brittle, it's completely untested, and it's hard to maintain. But more than that, if you want to add a new menu or change one of the existing ones, you have to override the entire template. LinguaPlone does this to get a <span style="font-style: italic;">translate</span> menu. BernArticle does it, apparently, for who-knows-what reason. CompositePack apparently uses JavaScript DOM manipulation to get another item in there. Nice.<br /><br />Now look at the <a href="https://svn.plone.org/svn/plone/review/plip142-componentised-content-menu">bundle</a> for <a href="http://plone.org/products/plone/roadmap/142">PLIP142</a>. This does a number of interesting things:<br /><ul><li>The menu is rendered as a <span style="font-style: italic;">content provider</span> (the Zope 3 component that underpins viewlets) by means of a 'provider:' expression at the bottom of <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/skins/plone_templates/global_contentviews.pt">global_contentviews</a>.</li><li>This invokes a <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/browser/contentmenu/view.py">view component</a> that prepares a ZPT-friendly structure.</li><li>The rendering of this data structure is now sane. Compare <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/browser/contentmenu/contentmenu.pt">this</a> template with the old <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/2.5/skins/plone_templates/global_contentmenu.pt">global_contentmenu</a>.</li><li>All the logic is implemented in Zope 3 components. These can be <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/tests/testMenu.py">tested</a>! There are now 50-odd tests covering the logic that used to be in one template (scary...)</li></ul>The components in this case use the Browser Menu infrastructure. This consists of one menu called <span style="font-style: italic;">plone.contentmenu</span> which represents the horisontal bar. This has a number of menu sub-menu items representing each of the <span style="font-style: italic;">actions</span>, <span style="font-style: italic;">display</span>, <span style="font-style: italic;">add </span>(aka <span style="font-style: italic;">factories</span>) and <span style="font-style: italic;">workflow</span> menus. Each of the sub-menu items in turn points to another menu that fetches the items to display in the drop-down. All of this is registered in <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/browser/contentmenu/configure.zcml">ZCML</a>.<br /><br />Notice how the sub-menu items are implemented as adapters. This is because they need additional logic beyond what the standard Zope 3 <span style="font-style: italic;">subMenuItem</span> ZCML directive can provide (and also because that directive doesn't seem to work in Five, at least it didn't in Zope 2.9). The implementations are found in <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/browser/contentmenu/menu.py">menu.py</a>.<br /><br />It is possible to register your own menus or override existing menus simply by registering new components in any package. For example, you could:<br /><br /><ul><li>Override the entire menu by providing a more specific adapter or an override for the <span style="font-style: italic;">plone.contentmenu</span> content provider. See the bottom of <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/browser/contentmenu/configure.zcml">configure.zcml</a> and the <span style="font-style: italic;">adapts()</span> specification for <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/browser/contentmenu/view.py">ContentMenuProvider</a> - anything more specific than <span style="font-style: italic;">Interface</span> could cause a different renderer altogether to be invoked.</li><li>Override a specific sub-menu item. Again, a more specific adapter registration could override the sub-menu items. The default items are simply registered for all content types, but you could choose to have a specific implementation of one of the menus for a specific content type.</li><li>Add a new sub-menu, either for all contexts or just those providing a given interface. Notice how the <a href="http://svn.plone.org/svn/plone/CMFPlone/branches/plip142-componentised-content-menu/browser/contentmenu/menu.py">sub-menu item implementations</a> all have an <span style="font-style: italic;">order</span> attribute, and that they are ordered with gaps - 10, 20, 30, 40. Add a new sub-menu item and register it as providing <span style="font-style: italic;">IContentMenuItem</span> with an order between any of those numbers, and you can control whether it appears before or after all the existing menus, or in-between two of them.</li></ul>The work is not quite finished, and there will be a lot of testing to be done, but already the bundle functions for the majority of use cases. Specifically, what remains is:<br /><ul><li>Make the JavaScript warning on the <span style="font-style: italic;">Delete</span> action work</li><li>Fix line breaks in the <span style="font-style: italic;">Display</span> menu</li><li>Ensure the selected item in the <span style="font-style: italic;">Display</span> menu is properly marked as such</li><li>Test with non-structural folders, folders with a single addable type, and with various combinations of permissions and roles to ensure the new menu behaves like the current one does.<br /></li></ul>We also need to decide whether existing customisations of <span style="font-style: italic;">global_contentmenu</span> should be allowed to override the default or whether we break all of them. Alec nearly has me convinced that breaking existing customisations is the right thing to do, since any customised version would break any other product that used the "new style" customisation techniques outlined above, and since the existing template is just scary.<br /><br />However, pending framework team review, I hope to see this in Plone 3.0. I'll miss having <a href="http://plone.org/events/sprints/past-sprints/amsterdam/pictures/alecm/image.2005-04-18.9358211149/image_view_fullscreen">days like these</a> trying to figure out how to make the <span style="font-style: italic;">Display</span> menu work under various conditions with some serious TAL voodoo, though...<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-585300293502209263?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com2tag:blogger.com,1999:blog-3263163041157204581.post-3551620068051521502006-08-16T11:24:00.000+01:002006-08-16T11:46:52.053+01:00Lovely new packagesThe pink fluffy people at <a href="http://lovelysystems.com/">Lovely Systems</a> have placed some new code in the <a href="http://svn.zope.org/">Zope Subversion repsitory</a>, right under our very noses. Thanks guys!<br /><br /><ul><li><a href="http://svn.zope.org/lovely.tag/">lovely.tag</a> is a tagging system, which from my cursory look (at both packages) may be somewhat similar to <a href="http://svn.plone.org/svn/collective/tagger">tagger </a>by Whit Morris of OpenPlans.</li><li><a href="http://svn.zope.org/lovely.ratings">lovely.ratings</a> is a ratings system for content. Again, there seems to be some overlap with Alec Mitchell's <a href="http://svn.plone.org/svn/collective/contentratings">contentratings </a>package.</li><li><a href="http://svn.zope.org/lovely.remotetask">lovely.remotetask</a> is a framework for executing remote tasks, i.e. on a different host.<br /></li></ul>The first two, certainly, are aligned with things that we may well want to include in Plone 3.0 and beyond.<br /><br />As we begin to realise the benefits of the Zope 3 re-use story, we need to be careful to examine what software already exists and how we may leverage it in Plone without having to re-invent too many wheels. Part of that may also be to look at how some of the existing packages that overlap could be consolidated, where this is practical.<br /><a href="http://svn.zope.org/"></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-355162006805152150?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com7tag:blogger.com,1999:blog-3263163041157204581.post-28792409869459064442006-08-15T16:02:00.000+01:002006-08-15T16:36:39.355+01:00Finally, another outletAfter months of thinking about it, it's finally time to create another excellent source of <a href="http://structuredprocrastination.com/">procrastination</a>. My friends in the <a href="http://plone.org/">Plone </a>community always tell me I write too much in my posts to the mailing lists. Rob Miller and others have rightfully suggested that I may need a blog to vent. Well, here we go.<br /><br />Expect this blog to contain more musings about Plone than anything else, but hopefully I will also write about my music, my job, and the rest of my life.<br /><br />Martin<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3263163041157204581-2879240986945906444?l=optilude.blogspot.com'/></div>Martin Aspelihttp://www.blogger.com/profile/11251335463579376973noreply@blogger.com2