text:
I've written an entire series of articles about Dependency Injection and the Inversion of Control. I've exhorted you to decouple your code and to ask for your dependencies instead of creating them yourself. I hope you've listened.
Now I'm going to discuss another way you can invert the control of your code – by using anonymous methods.
Anonymous methods were one of two major language features added in Delphi 2009 – the other being generics. Generics are probably easier to understand and use as they have a great use case with collections. Anonymous methods are a little harder to understand because their use and their purpose are not as easily seen. I hope that you'll start seeing their advantage after reading this post.
The basic idea is pretty simple – anonymous methods allow you to pass code, i.e. functionality, like any other variable. Thus, you can ask for functionality via an anonymous method just like you can ask for a dependency via an interface. Because you can assign code to a variable – or even pass code directly into a method – you can easily invert the control of your class by passing in code to your class instead of embedding it in the class itself.
One of the principles of Inversion of Control is "Don't call us, we'll call you". That is, if a class needs something, the class itself should ask for (call) the functionality, rather then doing that functionality itself. If a class needs to, say, record the processing of widgets as it happens, it should ask for a widget recording class and record things using the dependency that is passed in. A class should not create it's own instance of a widget recording class and then use it.
Given that example, it's not difficult to see how one could pass recording functionality into a class as an anonymous method.
Let's use the above discussion in a code example. As noted, perhaps your class needs to record the processing of widgets. Typically, you might do something like this in order to use good dependency injection techniques:
IWidgetRecorder = interface
procedure RecordWidgets(aNumberOfWidgets: integer);
Then, you'd pass an instance of that interface into your class:
MyWidgetRecorder: IWidgetRecorder;
MyWidgetRecorder := TWidgetRecorder.Create;
MyWidgetProcessor = TWidgetProcessor.Create(MyWidgetRecorder);
You'd store the widget recording interface and use it in your class as needed. And that's an excellent thing to do – your class is decoupled completely from the recorder, and you are using constructor injection to ask for your dependency.
Again, this is a great technique, and probably preferable most of the time. I don't want to leave the impression that what I discuss below is always a replacement for good, sound use of interfaces. However, it may not always be what you want to do.
As noted above, you can use anonymous methods to invert the control of your class. Perhaps declaring an interface and instantiating a class to implement it is too heavy. Perhaps the dependency is really simple and straightforward. In those cases, using a simple anonymous method to inject your dependency might be a better solution for decoupling your code.
For instance, you can declare an anonymous method type:
TWidgetRecorderProc = reference to procedure(const aCount: integer);
This will allow you to declare code that takes an integer – presumably the count of widgets being recorded – and does whatever you need it to without bothering the class that uses it.
From there, you can use this type in your classes:
TWidgetProcessor = class
FWidgetRecorder: TWidgetRecorderProc;
constructor Create(aWidgetRecorder: TWidgetRecorderProc);
procedure ProcessWidgets(aNumberToProcess: integer);
property WidgetRecorder: TWidgetRecorderProc read FWidgetRecorder write FWidgetRecorder;
This simple class declaration takes an anonymous method as a parameter to its constructor, and then exposes that function as a property. That's a bit of a commitment – you may not always want to do widget recording. If you wanted, you could not pass the anonymous method in the constructor and simply assign it to the property as desired. In any event, the widget recording functionality is implemented externally, and your class merely depends on the anonymous method type.
Then, you can implement the class as follows:
{ TWidgetProcessor }
constructor TWidgetProcessor.Create(aWidgetRecorder: TWidgetRecorderProc);
inherited Create;
FWidgetRecorder := aWidgetRecorder;
procedure TWidgetProcessor.ProcessWidgets(aNumberToProcess: integer);
WriteLn('Processing ', aNumberToProcess, ' widgets.');
Now, you have a class that can record widgets any way you want to – to the console, to a file, to email, a database -- whatever. And you don't have to know anything about the implementation of how the widgets are recorded. You just have a variable that refers to the code, which you can easily call in your code.
So, now we have a TWidgetProcessor that can record widgets with an anonymous method. Cool – but how? Well, you simply declare an anonymous method and pass it in. Here's an example which just writes out to the console:
procedure ProcessSomeWidgetsAndRecordToConsole;
WidgetProcessor: TWidgetProcessor;
RecorderProc: TWidgetRecorderProc;
RecorderProc := procedure(const aCount: integer)
Writeln('The Widget Recorder recorded ', aCount, ' widgets');
WidgetProcessor := TWidgetProcessor.Create(RecorderProc);
All this code does is declare an anonymous method that matches the declaration of TWidgetRecorderProc and writes the information out to the console. That's pretty simple. But what if you wanted to write it out to a file? Easily done without changing the TWidgetProcessor class at all.
procedure ProcessSomeWidgetsAndRecordToFile;
WidgetProcessor: TWidgetProcessor;
RecorderProc: TWidgetRecorderProc;
cFilename = 'WidgetRecord.txt';
RecorderProc := procedure(const aCount: integer)
SL: TStringList;
S: string;
SL := TStringList.Create;
if TFile.Exists(cFilename) then
S := Format('%s: %d widgets processed', [DateTimeToStr(Now), aCount]);
WidgetProcessor := TWidgetProcessor.Create(RecorderProc);
Of course, you could write a similar anonymous method to record the information to a database, send an email, or any combination thereof.
And just as importantly, if you want to test The TWidgetProcessor class, you might want to do so by passing in a TWidgetRecorderProc that does absolutely nothing:
RecorderProc := procedure(const aCount: integer)
// Do nothing, as this is a stub for testing purposes
And of course if your classes are easy to test, then they are very likely well designed. The ability to stub out functionality as above is a hallmark of well designed classes.
So now you have another tool in your Dependency Injection/Inversion of Control tool box. The power here is in the ability to decouple functionality from the class that needs that functionality. Anonymous methods provide a nice way to wrap up functionality in a single variable. Instead of injecting an implementation of an interface, with anonymous methods you can inject a specific chunk of code that will provide the functionality. Either way, you end up with testable code that will be more maintainable in the future.
(I have included the full source for this demo, as well as other demos, available on my Demo Projects repository on BitBucket.org)
By now I suspect that most of you have heard of generics. Perhaps you have started using them via the Generics.Collections unit, where you can find TList<T>, TStack<T>, etc. The Delphi Spring Framework contains an even more sophisticated set of collections and interfaces to those collections, including the very powerful IEnumerable<T>.
These are all very useful classes, and our code is made much simpler, easier to maintain, and more type-safe because of them. But using them merely makes us consumers of generics. If we want to truly take advantage of generics, we need to become producers of generic classes. It's a big step to see the benefit of generic collections, but the truly big step is to start seeing opportunities for the use of generics in your own code.
This past weekend, some of my team members and I attended the C-Sharpen event here in Philly. It was a valuable day, made particularly so by the presentations given by Steve Bohlen. He gave an excellent presentation on the topic I discussed above – how we need to start thinking as producers of generics and not merely consumers. In that presentation, he gave a simple example of how generics are powerful and can make your code simpler, more effective, and more powerful. So, I'm going to show that example here. It's a bit contrived, but very illustrative of how to think about generics.
First, consider the following code:
TOrderItem = class
ID: integer;
TOrder = class
ID: integer;
TCustomer = class
Now this code is very simple – a set of classes that might represent a simple order entry system. But right away, something should occur to you. All three have something in common – they are entities in your system. Down the road, you may want to act upon all the entities in your system, so you might create a superclass like so:
TEntity = class
TOrderItem = class(TEntity)
ID: integer;
TOrder = class(TEntity)
ID: integer;
TCustomer = class(TEntity)
But you might be frustrated because you want your TEntity class to have an ID field that is in use by all descendants, but that pesky TCustomer class can't oblige – it needs a GUID for its ID tag instead of an integer like the other classes.
Instead of fretting about the different types of ID tags, how about just create one that doesn't care what type it is? Well, this is where the power of generics comes in. How about you give the TEntity class a parameterized type – a generic – as it's ID, and then just tell all the classes what type their ID tag will be?
TEntity<T> = class
TOrderItem = class(TEntity<integer>)
TOrder = class(TEntity<integer>)
TCustomer = class(TEntity<TGUID>)
Now, given the above, your entities can all have ID's, but you don't have to have the same type for all of them. If a TEntity descendant needs an ID of a different type, you can just descend from TEntity and pass the correct ID type in the class declaration.
Again, the example is quite contrived, but I think it does a nice job of showing how you can starting "thinking generically" and not just accept a rigid type structure.
In addition, it illustrates why the more formal name for generics is "parameterized types". The type in the brackets is passed in to the type declaration, and then used within the class, just as method parameters are passed in to functions and procedures.
A simple, contrived example, sure. But hopefully it illustrates how generics can be used to turn you from a consumer of generic classes to making them a common tool in your code.
As a number of commenters have pointed out, my original example was sub-optimal. Rather than post a "correction" post, I've taken the liberty of updating and improving the original article.
As you have no doubt noticed, I updated the theme to my blog. I was never really happy with the one I've had for about a year now, so I tweeked and existing BlogEngine.Net theme to my liking. It appears to be working and looking fine, but l can't test it on all the browsers you people have, so please let me know if you encounter any problems or oddities.
One problem I am having is getting the lists, especially nested unordered lists, to work right. Not sure what is going on yet, but I'm learning.
I think I'll start a new series, and a new blog category, called "How Not To Code". In it, I'll try to highlight those little things that we've tended to do over the years that, well, are tempting for expediency, but probably not something we should be doing. There are a lot of "Here's the right way to do things", so this series will concentrate on the "what not to do". That will inevitably lead, of course, to a discussion of "What to do", but that's ultimately the point, I suppose.
Today's topic is "Don't directly passing function results as parameters to other functions and procedures".
For instance, consider the following code:
TData = record
a, b: integer;
TMoreData = record
c, d: string
function GetSomeData(aInteger: integer; aString: string): TData;
function GetMoreData(aBoolean: Boolean; aInteger: integer): TMoreData;
procedure ProcessData(aData: TData; aMoreData: TMoreData);
Then, imagine that you wanted to call ProcessData with the result of calls to GetSomeData and GetMoreData. It would be mighty tempting to simply call:
ProcessData(GetSomeData(aIntVariable, 'ocelot'), GetMoreData(True, AnotherIntVariable));
After all, think of all the typing you'll save!
You should avoid that temptation, because this way of doing things presents a few problems:
Instead of trying to compress everything into a single line of code, you probably would do something like this, instead:
TempData: TData;
TempMoreData: TMoreData;
TempData := GetSomeData(aIntVariable, 'ocelot');
TempMoreData := GetMoreData(True, AnotherIntVariable);
ProcessData(TempData, TempMoreData);
The above code solves the aforementioned problems – it is easier to parse in your head and you can easily see the data values in the debugger before they are passed to ProcessData.
Some good heuristics that fall out of this:
Lesson for the Day: Always pass variables, never direct function calls, as parameters to another procedure or function.
I have this friend who totally doesn't get Twitter. He doesn't get it so much that it actually kind of makes him angry that anyone does get – and like – Twitter. To him, it is a total waste of time in every way. He can't imagine why anyone would spend any time at all having anything to do with Twitter. And that's fine – to each his own. But I do find it amusing that someone would feel that way about a service used and enjoyed by millions of people.
I'm a Twitter lover. I find it entertaining, amusing, interesting, and good for my brain. I really enjoy reading it, and I really enjoy posting tweets. I get good news, good development information, and a good laugh when I read twitter. I get to express my self in short bursts that help me formulate my thoughts. What's not to like?
The common impression is that Twitter is for "letting you know what your friends are doing" – or at least that is how it was originally marketed. The common misconception is that Twitter is just a bunch of people posting "Now I'm eating lunch. Yum!", and perhaps it was that in the very beginning. But in the spirit of "Let a thousand flowers bloom", Twitter became a lot more than that. Twitter is a forum for expressing not only what you are doing, but what you are thinking, what you are watching, what you are reading, and anything things that you are up to. It is many things. It is a means of conducting a conversation across the world. It is a means of sharing information with like minded people . It can help you track your customers are thinking. It can be a source of entertainment. It can ensure you are up to date on the latest news, and it can even help foment a real live revolutions. Not bad for a site that posts things 140 characters at a time.
Here's the main reason why I like Twitter: It forces us to express ourselves in short, concise sentences. 140 characters isn't a lot, but it's not nothing. It is sort of real-world application of Strunk & White's exhortation of "Use fewer words". It's really quite amazing the amount of humor, wisdom, and pith people can cram into that little chunk of text. Anyone who cruises around the internets knows that, while it allows people to publish openly without the barrier of a publishing house, folks – this blog included – don't get the benefit of an editor. Twitter is the one place where you can know that if you read it, you'll get things in short, concise, crisp chunks. (And I should add that I pride myself on never using '4' and '2' and other similar shortcuts….)
I find that pleasing as a reader, and valuable as a writer. If I can express my thought in 140 characters, then I know that I've really distilled it to the essence of the thought. For instance, it took a while for me to get Hodges Law down to 140 characters but I did. (And I also now have the added advantage of it being in a single place that I refer to my awesome idea – as well as showing that I was the first to think of it. )
The other big reason I like Twitter is that it is an "easy read". If I have a few minutes to kill, I can pull out my Kindle and flip through the latest on my Twitter feed. I've knocked out more than a few pages of Twitter feeds at the Doctor's office. It also is perfect for solving that First World Problem of being bored while, ahem, "indisposed".
Third reason? It's a wealth of information about Delphi and software development. Many great developers tweet, and point to articles and blog posts that teach and explain about development. Want to know what the latest Delphi articles are? Follow DelphiFeeds. You can't say it is impossible to know what is going on with Embarcadero – they have a Twitter feed that updates with just about everything going on with the company. You can tailor your feed to bring you whatever you are interested in. I'm interested in Software Development, the NBA, specifically the Timberwolves, certain American Idol contestants, and generally funny stuff. That's exactly what my feed brings me.
Another feature that is both fun and powerful are hashtags. As far as I know, the power and coolness of hashtags was actually an invention of the Twitter community and not an original part of the "spec" for Twitter. According to this article – which is a great history and summary of hashtags -- the idea actually came from a guy named Chris Messina, and his idea has become part of the power of Twitter. Hashtags are used to create groups or topics. Sometimes they are fleeting – like a hashtag for the Superbowl – or sometimes they are ongoing, with people constantly adding to them, like the "#overheardathome" tag. Want to see what others are saying while American Idol is on? There's a hashtag for that. They have even made a difference in world events. The valiant folks fighting for freedom in the Arab Spring used twitter hashtags to inform the world and each other about important, world-changing events. Businesses are event starting to include hashtags in their advertisements (and of course, folks aren't always respectful of those tags…..) There's even a website dedicated to tracking the use of hashtags. From the humble beginnings of an idea from a single users, hashtags have made twitter into a useful and powerful communications medium.
It may have started out as a site to tell your friends that you are eating lunch, but Twitter has become a great place for some quick-witted comedy and entertainment. Heck, I tweet a lot about technology and programming, but I try hard to make a witty, funny comment every once and a while. Some people's sense of humor is just made for Twitter. One of my favorites is Josh Hara. If you are looking for a series of laugh-out-loud funny, but off-color tweets, look no further than Pauly Peligroso. There are tons of lists of (allegedly) funny people on Twitter. I should add that in my experience, the people that are "supposed" to be funny – that is, comedians whose names you know – aren't really that funny. But hands down, bar none, the funniest feed on Twitter is Sh*tmydadsays. In any event, Twitter can definitely make you LOL. (I only use "LOL" when I, well, actually do laugh out loud. You should follow the same rule.)
Another feature that dovetails on the straight comedy sites are some of the excellent parody sites. There's a whole slew of Star Wars characters on Twitter. Lord Voldemort of Harry Potter fame is enormously popular, on topic, and very funny. He and Severus Snape often exchange barbs. (Actually, there are quite a few folks tweeting as Severus Snape on Twitter….) You can keep track of Batman, Drunk Superman, Aquaman (Warning: he's a little…."salty"), Spiderman, Drunk Hulk, and just (presumably sober Hulk. (Apparently there are many facets to Hulk's personality). Want some history? You can follow Henry VIII, Calvin Coolidge, You can follow the history of the Byzantine Empire, the first 1000 days of the JFK administration, and real-time events of World War II. And that is just scratching the surface. Believe me. There is no end to the inanity, craziness, and imaginativeness of the folks on Twitter.
Yes, Twitter would be boring if it were nothing more than people telling you what they were doing. It may have been that at one point, but it's become way more than that. Shoot, a recent cover of Sports Illustrated had a hashtag for the cover article about Jeremy Lin. In the end, Twitter can me what you want it to be. You can follow technologists, pop stars, actors, authors, characters from books and movies, business, news sites, newspapers, bloggers, family members, humorists, athletes, historical characters, and more. You can keep up with technology, world events, politics, all manner of news and events, what your favorite authors/actors/singers are up to. It's really a huge, fascinating party that you can control to your heart's content.
Why anyone wouldn't be interested in that, I have no idea.
Drive: Hey, I'm as big a Ryan Gosling fan as the next guy, but holy cow is this movie ever boring, filled with lots of silent, forlorn staring and longing. In addition, I can't stand a movie where the "hero" drives away, leaving a bag with a million dollars in it lying on the pavement. Seriously?
Not one more word.
For many years, it has been very fashionable to say how "[Borland|CodeGear|Embarcadero] sucks at marketing". You could very easily establish your bona fides by bashing Delphi marketing. Everyone knows that Borland always sucked at it, and all the cool kids say so, right?
Well, I think those days are over.
First of all, I'm guessing that about 99% of the people saying this didn't understand the difference between "marketing" and "advertising". They aren't the same, just so you know. They overlap, but they aren't synonymous. The Wikipedia page for marketing starts out with "Marketing is defined by the AMA as 'the activity, set of institutions, and processes for creating, communicating, delivering, and exchanging offerings that have value for customers, clients, partners, and society at large.'" My personal definition is "whatever you do to make people aware that your product is for sale and what the reasons are that they should buy it".
Sales and marketing are related, but very different. In general, marketing's job is to create leads for sales to act upon.
I think that the root of much of the complaining over the years has been the result of a lack of advertising. People who don't see advertising think that there's no marketing going on. Marketing is much more than just running ads. Marketing activities include, but are very much not limited to, advertising. In fact, some of the most effective marketing is that which requires zero advertising.
For instance, Dropbox has a brilliant marketing strategy that has been amazingly successful and requires exactly zero budget for marketing or advertising. What do they do? They get people like me to try to get people like you to sign up. The more people sign up, the more potential paying customers they have. They give away 2GB of space (which probably costs them something like $0.000001….) and then induce those folks to do their marketing for them. They have been enormously successful doing this. They spend zero money on advertising, but they have a fantastic marketing plan that makes millions of people aware of what they have to sell. Awesome.
I'll concede that the marketing of Delphi has been historically "limited" or "hard to find" . I'll not concede that it has been "bad" or "terrible". The marketing itself has been good – there just hasn't been enough of it. Marketing success is largely a function of budget, and over the years, and the budget for marketing Delphi has not always been huge. As noted above, there isn't a direct relationship between marketing and money, but certainly money is a big boost. Limited budgets have made it harder to market Delphi, but that doesn't mean that the marketing that was done was done poorly.
Despite limited budgets, here has always been marketing going on around Delphi. Every new release resulted in many activities, a "world tour", webinars, etc. And here's a key point to remember: if you are an existing customer, then marketing to you is fairly easy. You already know the products and benefits. To a large degree, efforts spent on marketing that you see is wasted effort. The perfect marketing plan would be visible only to non-customers and invisible to existing customers. And here's the second thing to remember -- if you know that Delphi is on version XE2, and even the basics of the current feature set, then you have been successfully marketed to, whether you want to admit it or not! That's always been the case – if you knew about the latest release and it's features, you were successfully marketed to.
However, over the last few years, things have been getting better. And over the last year or so, things have gotten, well, really good. In that time, I've seen a marked and obvious increase in marketing activity and an rise in the quality of things done for Delphi and Embarcadero products in general. Clearly someone has decided to spend some money and make it a point of emphasis.
I now see the following on a regular basis:
The folks marketing Delphi are doing some really good work, and we should appreciate and recognize it. Embarcadero has clearly stepped up its game, and we should all give credit where credit is due.
Exceptions are all over the place in Delphi. Introduced way back in Delphi 1.0, they totally changed the way that folks looked at error handling. Previously, we'd do things like:
ErrorCode := DoSomething;
if ErrorCode > 0 then
end else
We had to constantly interrupt the flow of our code in order to make sure that all is well. Exceptions changed all that by letting you put all the error handling at the end, in a try…except block – out of the way of the flow of your code -- where you could handle things separately, leaving you to worry about how things should go, and not how they might go wrong.
Way back for Borcon 2004, I wrote a paper on exception handling called "Exception Handling for Fun and Profit". You can read that and get a good idea on the proper way to handle exceptions. It is eight years old, but it's still all good advice.
What I want to talk about here, though, is the best way to write your own exception classes and exception class hierarchies. The Runtime Library gives you a number of Exception types, and it uses most of them. You are, of course, free to use any of those exceptions declared in SysUtils.pas and elsewhere, and of course you can simply create an exception from the base class Exception. But most often when writing your own library code, the standard exception classes are not enough. So I'm going to try to give you some ideas on how you can and why you might create your own exception classes.
A note before I start: Exception hierarchies should be part of library code; that is, code you write for use by other applications. As noted in my aforementioned article on exceptions, application developers should trap exceptions, and library code writers should raise exceptions. Exception hierarchies are part of developing library code, so this article really only pertains to that side of the fence.
A note before I start: Exception hierarchies should be part of library code; that is, code you write for use by other applications. As noted in my aforementioned article on exceptions, application developers should trap exceptions, and library code writers should raise exceptions. Exception hierarchies are part of developing library code, so this article really only pertains to that side of the fence.
The first thing I'll tell you is that you should never raise a plain exception:
raise Exception.Create('An error occurred');
I can't think of any reason for ever doing that. It provides no useful information about the type of exception and why the exception being raised, leaving consumers of your code with little helpful information.
So, as you've probably noticed, I like to say "You should never do <this>". And of course, when I do that, it's incumbent on me to say what you should do instead. So here goes.
First, you should always raise a specific exception for a specific exceptional situation. If it's a "normal" exception, use on of the standard Exception classes that are part of the RTL. For instance, if you are dealing with streams, and you have an error, you might raise an EStreamError.
Most often, though, you want your exception to be as precise and exact as possible. This way, it will be easier to pinpoint exactly what went wrong when the exception is captured and displayed. And in order to do that, you should create your own exception hierarchy. If an existing exception type isn't perfect for the situation, then don't be afraid to define one that is.
And when you do that, the hierarchy you create should be flat and wide. Flat and wide exception hierarchies allow for the simple organization of similarly purposed exceptions. Here's what I mean by that.
I'll use my class library THTMLWriter as an example. It it, there is a unit called HTMLWriterUtils.pas that contains the following code:
EHTMLWriterException = class(Exception);
EEmptyTagHTMLWriterException = class(EHTMLWriterException); // Tested
EOpenTagRequiredHTMLWriterException = class(EHTMLWriterException); //Tested
EHeadTagRequiredHTMLException = class(EHTMLWriterException); // Tested
ETryingToCloseClosedTag = class(EHTMLWriterException); // Tested
ENotInListTagException = class(EHTMLWriterException); // Tested
ENotInTableTagException = class(EHTMLWriterException); // Tested
ENotInCommentTagException = class(EHTMLWriterException); // Tested
ENotInFieldsetTagException = class(EHTMLWriterException); // Tested
ENoClosingTagHTMLWriterException = class(EHTMLWriterException);
ENotInFrameSetHTMLException = class(EHTMLWriterException); // Tested
ENotInMapTagHTMLException = class(EHTMLWriterException); // Tested
ENotInFormTagHTMLException = class(EHTMLWriterException); // Tested
ENotInObjectTagException = class(EHTMLWriterException); // Tested
EClosingDocumentWithOpenTagsHTMLException = class(EHTMLWriterException); // Tested.
ETableTagNotOpenHTMLWriterException = class(EHTMLWriterException); // Tested
EParamNameRequiredHTMLWriterException = class(EHTMLWriterException); // Tested
ETagIsDeprecatedHTMLWriterException = class(EHTMLWriterException); // Tested
ENotInSelectTextHTMLWriterException = class(EHTMLWriterException); // Tested
ECaptionMustBeFirstHTMLWriterException = class(EHTMLWriterException); // Tested
EBadTagAfterTableContentHTMLWriter = class(EHTMLWriterException); // Tested
ENotInDefinitionListHTMLError = class(EHTMLWriterException); // Tested
ECannotNestDefinitionListsHTMLWriterException = class(EHTMLWriterException); // Tested
ECannotAddDefItemWithoutDefTermHTMLWriterException = class(EHTMLWriterException); //Tested
This is an example of a "flat and wide" exception hierarchy. The hierarchy is "flat" because there are only two levels of inheritance – the base class and a large number of descendants. A class diagram of these classes would be "flat" because there isn't much distance from the top to the bottom of the inheritance. It's "wide" because there are a lot of sibling classes on the second level of inheritance. The class diagram would take a lot of horizontal space if it were laid out on paper.
How does this all work? First, I declared a base type, EHTMLWriterException. All the exceptions raised in the THTMLWriter library will be a descendant of this type. As a result, you can easily check the type of an exception, and if the type is EHTMLWriterException, then you know what library raised the exception. When you are using the THTMLWriter library, you can easily trap all the exceptions raised by the library within your exception handling code by simply calling:
//code that raises an exception in THTMLWriter....
on E: EHTMLWriterException do
//you know that the exception came from THTMLWriter
Second, I declare a large number of very specific descendants that are raised in very specific situations. Their names are very descriptive, and they are usually raised only in one place – the exact place that the error occurred. This makes locating the cause of the exception much easier. Precisely named exceptions can be easily searched for in code.
For instance, here's an example of some code calling a very specific exception:
function THTMLWriter.OpenParam(aName: string; aValue: string = cEmptyString): IHTMLWriter;
if TStringDecorator.StringIsEmpty(aName) then
raise EParamNameRequiredHTMLWriterException.Create(strParamNameRequired);
Result := AddTag(cParam)[cName, aName];
if TStringDecorator.StringIsNotEmpty(aValue) then
Result := Result[cValue, aValue];
Here you can see that the code raises an exception named EParamNameRequiredHTMLWriterException. The class name alone tells you that it is an error from the THTMLWriter library, and that it was raised because a parameter name was required but not found when the call was made. Just the exception's class name has a lot of information. In addition, you'll note that when I raise these specific exceptions, I include a very specific, detailed error string explaining what happened. In my view, you can't have enough information in an error message.
Thus, if you end up raising this exception, you'll get this:
Given all that, if you can't figure out exactly what the problem is and exactly where it occurred, well, then I'm not sure you are in the right business.
Since it is fine – and even desirable – for exception hierarchies to be wide, you shouldn't be shy about declaring many exception classes as direct descendants of your one main exception class. You'll note above that even in a small library of code like THTMLWriter, I've declared 23 exception types. I see nothing wrong with having a large, very specific set of exceptions that you can raise throughout your code library. As I said before, if your exception type is only raised once, that's fine – it's very easy to find the location of an exception that is only raised in one place.
So there it is – make your exception class hierarchies flat and wide, use good exception messages when raising them, and you'll enable the consumers of your code to easily see where problems are arising and to quickly deal with them when they do.
A while back I wrote about why I got my Amazon Kindle Fire, and in that post I promised you that I'd write about my thoughts about owning the Kindle. And since I'd rather rub shredded fiberglass in my eyes than break a promise to you fine people, here are my thoughts on owning an Amazon Kindle
Final verdict: I'm happy with my Kindle Fire – I like using and having a tablet – but I'm going to save up an buy a "real" tablet in the fall. I'm interested in the Google Nexus Tablet – or at least in concept. I like having a Nexus phone, and I'd like to have the same thing in a tablet.
I am now going to go on a rant about Twitter clients – mobile Twitter clients in particular (though some desktop clients are rant-worthy as well). I am going to do this because I can't understand why they are such a pain in the ass and work so badly, when they could so easily work so well.
Okay, first, don't get me wrong. I really like Twitter. (If you want, you can follow me, I'm @nickhodges -- no surprise in that handle, eh?) I like it because it's a great place to keep up on news, find interesting articles, read funny stuff, and to post your thoughts in short, pithy statements of 140 characters or less. It's also a great time killer. If you are waiting at the doctors office, it's a much better way to pass the wait than looking at a two and a half year old copy of People Magazine. It's interesting, fun, never the same thing twice, and frankly, I'm a little addicted. I do almost all of my twitter reading on my phone or on my wonderful Amazon Kindle .
But yet reading Twitter on my mobile devices drives. me. crazy. When it comes to mobile Twitter clients, I'm not addicted -- I'm inflamed with a rage that burns like the heat of a thousand suns.
I've tried just about every one out there. They all drive me insane. And so here is my rant:
Bottom line: Mobile twitter clients stink and they make me want to bash public monuments with a sledgehammer. (I'd never do that, really, but I want to when I go back from checking my mail and the stupid TweetCaster moves me to a tweet that was posted 23 seconds ago.)
Phew, okay, I feel better now.
So I've been writing about Interfaces, and mostly talking about how you should use them. But as important as designing and using the interfaces themselves is how you implement those interfaces. I talked about the basics in the previous article, but there are some things that you can do to make implementing an interface a little easier.
I'd like to show one way that you might go about it for the purpose of starting a discussion about the technique. I've seen the method I'm going to describe below used in a number of places, most notably back in WebSnap. (Remember that? WebSnap was actually a pretty cool library of code, doing a lot of things in a somewhat MVC fashion before MVC and web development was in, well, fashion.)
Anyway, here is how the implementation pattern I'm talking about here works: You create a "base" class that implements each member and property of the interface. Then, you add a virtual, abstract method that corresponds to each interface method with a naming convention of DoMethod. You then call that virtual, abstract method inside the implementation of the interface methods.
This base class then becomes the parent for any class that implements the interface. In essence, you create an easy-to-inherit class that easy implements the interface so you don't actually have to worry about implementing the interface over and over again.
Naturally, this is hard to explain, so a code example is in order.
Consider the following simple interface:
IDemoInterface = interface
procedure ProcessSomething;
function ProcessData(aString: string; aInteger: integer): Boolean;
Nothing fancy, and obviously illustrative.
To do what I'm talking about, you'd implement this interface as follows:
TBaseDemoInterfaceImplementor = class abstract(TInterfacedObject, IDemoInterface)
procedure DoProcessSomething; virtual; abstract;
function DoProcessData(aString: string; aInteger: integer): Boolean; virtual; abstract;
procedure ProcessSomething;
function ProcessData(aString: string; aInteger: integer): Boolean;
procedure TBaseDemoInterfaceImplementor .ProcessSomething;
function TBaseDemoInterfaceImplementor .ProcessData(aString: string; aInteger: integer): Boolean;
Result := DoProcessData(aString, aInteger);
So, what you have now is a class – TBaseDemoInterfaceImplementor – that can be used to really implement the functionality of the IDemoInterface. You have an abstract class to inherit from, and two methods to override to implement the functionality.
So, of course, the class that you'll actually use would look something like this:
TRealDemoInterfaceImplementor = class(TBaseDemoInterfaceImplementor)
procedure DoProcessSomething; override;
function DoProcessData(aString: string; aInteger: integer): Boolean; override;
function TRealDemoInterfaceImplementor.DoProcessData(aString: string; aInteger: integer): Boolean;
ShowMessage(Format('I am processing the following data: %s and %d', [aString, aInteger]));
Result := Random(2) = 1;
procedure TRealDemoInterfaceImplementor.DoProcessSomething;
ShowMessage('I am processing something!');
What happens is that the implementation becomes much less painful once you have the base class defined with the details of implementing the interface neatly tucked away. You are doing simple class inheritance at that point.
Now I've thought about this pattern for a while, but I'm not sure about it. I'm very interested in hearing what you all think. I guess one downside is that the class doesn't clearly declare that it implements a given interface. Perhaps a naming convention would do that?
On the one hand, it seems a nice way to create a class library that implements an interface. To me, it seems like a good use of polymorphism. There may be times when you want a large chunk of your library to implement a "basic" interface, and using this inheritance trick can make that easy. Once you create a base class, you can now build a class hierarchy based on that class, with all the classes implementing the interface with much less hassle and more cleanly. In addition, it makes it easier to create any number of descendants from the base class if you want to have a number of different implementations for the interface. For instance, if you had ICreditCard, you might create TBaseCreditCardImplementor, making it easy to descend from and create TVisa and TMastercard, etc.
Pattern? Anti-pattern? Maybe I'm crazy and this is a really silly idea. Maybe this is a known pattern already and I'm just ignorant. Maybe this is the coolest idea ever.
What do you guys think?
The views I express here are entirely my own and not necessarily those of any other rational person or organization. However, I strongly recommend that you agree with pretty much everything I say because, well, I'm right. Most of the time. Except when I'm not, in which case, you shouldn't agree with me.
Powered by BlogEngine.NET 126.96.36.199
Theme by Mooglegiant and modified by Nick Hodges


text:
Gallery > Album
Saltash Regatta
Showing images 1 to 10 of 11.
Gallery > Album
Showing images 1 to 10 of 11.
© Copyright Pirate FM
Pirate FM cannot be held responsible for the content of external links.
Our website uses cookies. Learn more about cookies and how to manage them.

subset: commoncrawl


text:
Post replays here.
NOTE: Try to avoid talking in your match. It messes up the replay.
Spoiler for Guide to Fast Copy & Paste:
NOTE: This guide is only for Windows Computers.
Step 1. Highlight the first letter of the code.
Step 2. Use your scroll bar and scroll all the way down.
Step 3. Hold the ''shift'' key on your keyboard, and click on the last letter of the replay code.
Step 4. Right click and select ''Copy''
Step 5. Go to Stick Empires, and click on ''View Replays''
Step 6. Hold the ''Ctrl'' key. on your keyboard, then hold the ''V'' key.
The code should now be pasted, and you now press the ''Load Replay'' button for the replay to be played.


text:
Digital Scrapbooking Inspiration
In The Groove
The holidays are a magical time for many reasons. The gathering of family and friends, festive food, traditions, music, and…memories. And so, The Groove is celebrating memories this month, specifically "Vintage Memories" – a theme that suggests reaching back to a time gone by, capturing the essence of what made those times special.
Look through your favorite "vintage" photos and put together a layout for our special "Vintage Memories" contest (see below for details). And of course, don't forget to download this month's gorgeous freebie from Scrapbook MAX! Booster Pack Store Designer Deanne Gow-Smith (see below).
Vintage Memories
What else are our photographs but memories? And what better way is there to add depth, texture, and "lasting-ness" to those photos than through carefully crafted scrapbook layouts? How incredible that we live in a time where the images of our past can be viewed in the present, and carried with us into the future! Get inspired by the dazzling vintage layouts below ("Family Retro by grannywin, and "Alice" by MaggieMae):
Grannywin would like to give the following credits: My thanks to Weeds and Wildflowers.com for the grunge paper, SAC for the corners, and Granny for the glasses. I appreciate all the "goodies".
Digital Scrapbooking Tips
Groovy Tip #1: You work hard on your scrapbooks. Remember to save your Projects and Published files, and original Templates regularly on CD-R for "safe-keeping". By default, these are stored on your computer under My Documents > Scrapbook MAX!
Groovy Tip #2: If you have lost or forgotten your password for our Online Community, please click on the following link and then follow the instructions to reset your password.
Scrapper Profile
Diana Carmichael
Newton, Kansas
Meet the generous and dynamic Diana Carmichael, otherwise known as "knzus". In addition to being a regular and helpful presence in our Community, Diana is a designer for the Scrapbook MAX! Booster Pack Store. Get to know her better!
Q. Tell us a little about yourself.
A. I'm a born-and-raised native Kansan, married for 12 years to my soulmate, Jerry, who is my love and my best friend. I have two grown sons from a previous marriage, and six grown stepchildren. Together, we have been blessed with five grandchildren so far – three boys and two girls – whom we adore and find such joy in spending time with. Known as "knzus" on the SBM forums, I'm a designer for Scrapbook MAX! in my spare time, which amazingly parallels my regular work as a home-based webpage designer/consultant.
Q. How did you get started on digital scrapbooking?
A. I had begun just as recently as a year ago to scrapbook with "real" materials for my genealogy projects (I had never scrapped before in my life!), when one day, while perusing the internet for downloadable/printable papers, I ran across Scrapbook MAX!. I read all I could about the program and digital scrapbooking. I downloaded the trial version and the rest, as they say, is history!
Q. What are your hobbies/interests (other than digital scrapbooking of course)?
A. Besides the grandkids and genealogy, I have been an avid gardener all of my life (my garden areas grow larger with each passing year!). I read almost non-stop during the rest of my time – mostly Christian fiction and anything historical, especially that related to the 1800s. I also sketch (pencil) and sew (quilts and crafts), and Jerry and I enjoy being a part of and active in our church.
Q. Where do you get your layout ideas?
A.There is a lot of variety in this answer! Sometimes I will use life around me, or see something in a book or magazine, or be drawn to the way someone else has done theirs. It all depends on the moment and the mood!
Q. Tell us about the layout you are most proud of and why.
A. This is most decidedly the family pose from our family portraits we had done in 2006. I matched the papers and embellishments to the predominant color we all wore, which gave it a very classy holiday look. It happened to be near the holiday season at the time of the portraits, so it made for a beautiful layout that was printed and framed for our parents.
Q. What do you think makes Scrapbook MAX! so popular?
A. It's such an easy program to understand and learn, and has a great user-friendly interface. Problems figuring something out? Just use the Scrapbook MAX! Help or User's Guide (under "Help" in the browser menu). There is SO MUCH that can be done with this program!
Q. What is your favorite Scrapbook MAX! tip or trick?
A. The one I use most is very simple: To give an overall "matching tint" effect to a layout, I choose a paper with the color I want to use via the "Paper Scrap" button and move the "Transparent/Opaque" slider until I find the amount of transparency I like and apply it. This adds a little bit of tint to the whole layout and even makes your photos match the layout colors.
Q. Who is your favorite movie star?
A. The outspoken Katherine Hepburn because she brought such an unconventional and straightforward quality to any movie she was part of during her lifetime. I especially like her in the movie "Rooster Cogburn (…and the lady)" in which she co-starred with John Wayne (1975).
Check out some of Diana's favorite layouts below!
**Free** Holiday Template and Kit!
'Tis the season of giving – and Scrapbook MAX! wants to give YOU a very special holiday gift!
When you purchase Scrapbook MAX! between November 20 and December 31, 2007, we will send you a 5-Page Christmas Template Kit and a beautiful Christmas Booster Pack Kit absolutely free! These gorgeous kits were created by Booster Pack Store Designer Julie Clark and have a total value of $9.90.
Sample pages from the FREE Holiday Template (limited time offer)
Remember – Scrapbook MAX! digital scrapbooking software makes a great holiday gift for all the scrapbookers on your list (even if that person is you!). And no matter who you are buying for, when you purchase Scrapbook MAX! between November 20 and December 31, 2007, you get a little special something for yourself!
Buy Scrapbook MAX! (and get a free gift) today!
The Groove's Monthly Freebie
It's time to "scrap" all those fabulous fall photos you've taken in the last couple of months! Here to add some dazzle to your digi pages is a gorgeous set of autumn-themed embellishments generously shared by Scrapbook MAX! Booster Pack Store designer Deanne Gow-Smith!
Creative Genius
Make holiday ornaments and decorations with Scrapbook MAX!. We went wild for this crafty idea from Scrapbook MAX! Community Member, Jelayne. Here's what she had to say about her "ingenious" hobby!:
"I am a crafter who can't draw a straight line to save my life. So I use
digital art / software to do the drawing part (i.e., of handmade decoration projects) and then cut, paste and glue to my hearts content. I like to do easy projects that can be done in a short amount of time and that don't cost an arm and a leg to make. Often I see a craft idea in a magazine and I use a program like, Scrapbook MAX! to recreate
it for my own use."
– Jelayne U. (aka Jo or workingjo3), Monroe. WI
Jelayne has generously shared her Christmas Party Template with you so that you can make your own Christmas decorations with Scrapbook MAX!. Make adorable Name Cards for Place Settings (can also be used as Christmas Tree Ornaments), and a lovely Christmas Table Centerpiece. Thanks, Jelayne!
Contest: Vintage Memories
Time to pull out the photos from a "time gone by" and create a Vintage Memories layout! As usual, we leave the definition of "Vintage" up to you – but we want to see something in the photo or in the layout design that evokes another era. We've seen some gorgeous examples already in the gallery, so we're anticipating beautiful entries this month!
Three winning layouts will be published in the next issue of The Groove: 1st prize is a $20 gift certificate to the Scrapbook MAX! Booster Pack Store! 2 runners up will each receive an official Scrapbook MAX! mousepad.
To enter, publish your layout as a JPEG image using the 'High Quality' and 'Web/Email' options, and upload it to the Vintage Memories contest page in the Scrapbook MAX! gallery. All entries will be available for viewing. Contest closes Thursday, December 27 , 2007, 5:00pm (CST). ** Note: You must be a registered member of the Scrapbook MAX! forums to enter this contest. Register for free here!
First-Place Winner in our
"Real-Life Superstars" Contest!
Layout by Marion
This layout is a touching tribute to a very special man. Marion's beautiful page captures the essence of what it means to be a real-life hero; a person who teaches, exemplifies, and inspires the best human qualities.
Our Runners-up!
Layout by Paula K., Cascade, WI
Paula K. is right – this winning smile instantly makes you feel joy! (We think the color-coordination in this page also has superstar quality!)
Paula would like to give the following credits: The frame cluster is from Moonbeam's Been Framed pack. The "recolored" button flowers are from "Dragon Dreams" by Zan, the papers and other embies are from "Dark Forest" found in SBM
Layout by grannywin
Grannywin has cause to be proud of the real-life superstars in her life. We applaud the creativity of her evocative, "fiery" color scheme, which reminds us of the challenges and dangers these firefighters face daily.
Vintage Embellishments! We love how the embellishments and background schemes of these two layouts evoke the same era as the photos. You'll find great vintage-themed embellishments in the Sharing Corner – why not search there for the perfect elements to compliment your "Vintage Memories" contest layout (hint! hint!) (Thank you Marion and Gotart for your contributions!)
The Groove Wants YOU!
Have a Lois Lane complex? Put it to use by contributing to The Groove! We're always looking for fresh ideas to make The Groove fun and exciting – just like our readers! Tips, musings, inspirations, ingenious scrapbook ideas – if you've got 'em, we'd love to read 'em! Email The Groove your bright ideas today! Contact us at [email protected]
Next Month in The Groove
The Groove celebrates "Celebrations!". Plus, look for December's "Vintage Memories" contest winners!


text:
Vias Capital necesitaba un nuevo diseño de logotipo y lanzó un concurso de diseño en 99designs.
Un ganador ha sido elegido entre 137 diseños de 36 diseñadores freelance.
Vias Capital Management
I am a 32 year old male FX/Commodities portfolio manager. I have been trading for 10 years and this will be my first attempt at branching out on my own. I have had the good fortune of working at very solid institutions and feel it is my time to build one of my own. I am serious yet affable person who enjoys challenges and is willing to do whatever it takes to be successful. Personally success does not entail vast amounts of money but personal fulfillment through the accomplishments of goals. In this case my goal is to build something of my own that will be synonymous with aggressive yet stable growth. I enjoy my line of work because it resembles puzzle solving in what often feels like 4 dimensions. It is extremely difficult to surmise some semblance of the future and attempting to do it everyday makes for an interesting existence. It also teaches you that sometimes being right 40% of the time is a real achievement. The company is named after me and means "ways" or "paths" in Spanish.
One of the major goals of a money management company is capital raising. If there are no assets to manage there will be no business. As a new company I will probably raise funds from small investors to begin with but the end goal is to ask for institutional money from endowments and pension funds. In short, my audience is everyone who needs a good investment and has the capital to invest. In general this will be intelligent people with good educations who know something about finance. Most will be older than 30 and mostly white males though I hope to expand my capital raising to other demographics as well. Mainly I will be targeting investors who are fed up with illiquid and opaque investment strategies. Unlike hedge funds Vias Capital Management funds will be completely liquid and transparent so that investors can have confidence that there money is safe and accessible to them at a moment's notice.
I am looking for a logo to represent my new money management firm - Vias Capital Management
Here are a few things to think about:
1. Nothing whimsical
2. Though it's going to be primarily a foreign exchange fund currency symbols will be too obvious.
3. The typeface should be clear, elegant and bold. Something that stands out
4. The logo should work with and without the name of the company next to it. I'd be open to it being just the name set up in an interesting way but think I'd prefer to have some sort of a logo with it or at least incorporated into the name.
Please feel free to experiment with colors as long as it isn't too bright.
The files we will require are:
Print file format - .ai (CMYK)
Web file format - .jpg and layered .psd (RGB)
Please do not use any stock images or clip art in the logo
In general, I want my company and hence my logo to represent stability, growth and responsibility. I want it to have a sense of permanence and longevity. A logo that will be timeless and always contemporary. A cool logo that instills confidence and peace of mind. Your money is safe and growing at Vias Capital Management.
Descubre cómo funciona un concurso de diseño u obtén más información sobre nuestros servicios de diseño de logo.


text:
The 2008 British Snowboard and Freeski Tour returns this summer, announcing six new dates, introducing a brand new venue and continuing to represent and showcase the highest level of Snowboard and Freeski competition in the UK.
New to the British Snow Tour, Halifax Ski and Snowboarding Centre will join the list of existing and successfully tested venues: Chatham, Norfolk, Castleford, Milton Keynes and Glasgow for 2008. By adding new venues and continuing to incorporate a dedicated schools tour program, which will visit over 6,000 kids and give away 1,000 lessons, the British Snowboard and Freeski Tour will create new breeding grounds for emerging talent and continue to provide a path from grass roots participation through to international competition.
British Snow Tour dates for your diaries:
5th & 6th July 2008 ñ Halifax, British Big Air Championships
12th & 13th July 2008 ñ Chatham, British Slopestyle Championships
19th & 20th July 2008 ñ Norfolk, British Snowboard/Skiercross Championships
20th September 2008 ñ Castleford, British Slopestyle Championships
27th September 2008 ñ Milton Keynes, British Big Air Championships
4th October 2008ñ Glasgow, British Snowboardcross/Skiercross Championships
The 2008 British Snow Tour will also be returning to this yearís Metro Ski and Snowboard show for the Invitational Championships, to keep up-to-date with new event news and info, check out the British Snowboard and Freeski Tour website: www.britishsnowtour.com
The British Snowboard Tour continues to be the only UK event to award competitors with prestigious Ticket to Ride (TTR) points and TTR World Snowboard Tour Ranking. Giving UK riders the opportunity to not only win British Championships Titles, but secure World Ranking Points. Artificial Events = TTR ONE(1)STAR event, Indoor Events = TTR TWO(2)STAR event, The BRITS = TTR THREE(3)STAR event, for more information and to find out where UK riders are currently ranked check out: www.ttrworldtour.com


text:
Keeping Food Safety on the Front Burner for Christmas
By Kerri Lindberg, LMC Dietary Intern
As we begin to delve deeper into the season of fancy foods, now is the time to briefly review important food safety when cooking our favorite holiday meats. After all, foodborne illness is a quick way to dampen anyone's holiday.
From the store…
Fresh chicken, turkey, fish, or shellfish: use in 1-2 days
Fresh beef, lamb, pork, veal: use in 3-5 days
To the preparation…
Keep in mind, these temperatures should always be taken in the thickest part of the very center of the cut of meat. When stuffing poultry, be sure the stuffing reaches the proper temperature also.
Beef, veal, lamb, pork, Cornish hens, fish, shellfish: 145°F
Ground Beef: 160°F
Whole Turkey and Chicken: 165°F
Stuffing: 165°F minimum
Wild Game: 165°F
Eggs, venison: 160°F
And back for more…
Leftovers should be used in 1-4 days and need to be reheated to 165°F
Here's a safe way to prepare a potentially unsafe holiday favorite:
Egg Nog
Yield: 2 quarts Serving size: ½ cup
1 quart of 1% milk
6 eggs
1/4 teaspoon salt
1/2 cup sugar
1 teaspoon vanilla
1 cup half-and-half, whipped
ground nutmeg
Remember: A dash of rum won't make it safe! Alcohol cannot be relied upon to kill bacteria.
• Heat milk in large saucepan until hot (do not boil or scald). While milk is heating, beat together eggs and salt in a large bow l, gradually adding the sugar.
• Slowly add the hot milk mixture to the egg mixture stirring continuously.
• Transfer the mixture back to the large saucepan and cook on medium-low heat. Stir constantly with a whisk until the mixture thickens and just coats a spoon .The food thermometer should register 160° F. Stir in vanilla .
• Cool quickly by setting pan in a bowl of ice or cold water and stirring for about 10 minutes.
• C over and refrigerate until thoroughly chilled, several hours or overnight.
• Pour into a bowl or pitcher. Fold in whipped cream. Dust with ground nutmeg and enjoy!
Recommendations provided through USDA and CDC.


text:
The perfect lunch—by mail. If you know someone who loves real deli fare, sending this gift will cement your status as the most clever, generous friend they have. Some assembly is required, but considering it has been known to make grown men weep in appreciation, we think it's worth it.
Included: Jewish Rye (Pumpernickel in Brooklyn Reuben), sliced deli meat (Corned Beef, or Pastrami, or Turkey), freshly sliced Emmentaler Swiss cheese, Zingerman's potato chips, Coleslaw, Sauerkraut, Russian dressing, garlicky pickles, Magic Brownie Bites.
Download our professional-grade instructions, which also come inside the box. Or watch this tutorial on how to make a Zingerman's reuben!
How to Make a Reuben from Zingerman's Community on Vimeo.
"The Reuben is killer."
Barack Obama
"Zingerman's sandwiches are an 11 on a scale of 1 to 5."
"Now that's a sandwich!"
Michael Ivins, The Flaming Lips
"Their reubens are so good, I became that tedious person talking to my family about them in detail on the phone."
Mindy Kaling
"Your Reuben Sandwich Kit absolutely floored my parents. Easily the best present I have ever gotten them. It made up for 37 years of me being an awful son. They cannot stop talking about how great it was."
Paul M., Swannanoa, NC
The best reuben in America
Twenty Best Sandwiches in America, Food & Wine
"Zingerman's...made Reuben-giving a sacred holiday tradition."
New York Magazine
There's been a small change we want to let you know about.
The recipe for Binny's Brooklyn Pastrami Reuben Sandwich Kit has changed:
We temporarily ran out of
Pumpernickel Bread
so we've included
Jewish Rye Bread.
New foods, discounts, love letters.
If you are not pleased with any aspect of your order, please let us know.
We'll quickly replace it or refund your hard earned cash.
And you never, ever have to return anything.


text:
Your Saint Cloud Chiropractor
Choosing the right Chiropractor is an important choice to make. Dr. Cullinane and his staff are trained on the latest chiropractic treatments & technologies...
Safe & effective Chiropractic
Chiropractic care is a safe, effective and natural approach to managing pain and other health related issues. We invite you for a complimentary, no obligation consultation today.
Reclaim your optimal health!
Chiropractic is the holistic healthcare leader. Your optimal health depends upon a balance of proper biomechanical function, proper biochemical function and mental state.
Saint Cloud Chiropractor
Thank you for visiting the website of Saint Cloud Chiropractor Dr. Jay Cullinane and St. Cloud Chiropractic, Inc. Wellness Center - located in historic downtown Saint Cloud Florida 34769. It has been Dr. Cullinane's privilege to help thousands of people overcome their pain over the decades. People with low back pain, sacroiliac pain, sciatica, leg pain, knee pain, foot pain, neck pain, shoulder pain, arm pain, elbow pain, wrist pain, hand pain and headaches have all responded well.
Since 2007, Dr. Cullinane has been intensively studying nutrition. This education has allow for careful analysis of your individual nutritional needs, not some generalized prepackaged program. Dietary advice and proper nutritional support can help you reclaim a feeling of well being you haven't experienced for years.
Dr. Cullinane also offers a monthly weight loss lecture series, Dr. Jay' Eat 'Til Full Lose Weight Club. You will be taught how to lose weight by eating more food. April's lecture is canceled due to the coronavirus pandemic.
Check out Dr. Cullinane's blog and sign up to receive updates.
Like Saint Cloud Chiropractic, Inc. on Facebook and you'll find brief summaries of recent research.
Check out our trans fat section to learn how much trans fat is actually in your zero gram of trans fat food product. It's not zero!
Explore the rest of the website for recommended reading and viewing, as well as, more information about Dr. Cullinane and Saint Cloud Chiropractic, Inc.
www.saintcloudchiropractor.com and remember to come back often.
Yours in health,
Dr. Jay Cullinane
Privacy Policy
Yours in health,
Dr. Jay Cullinane
Privacy Policy
As of 4/4/2020 there were 1,051,635 cases of COVID-19 worldwide and 56,985 deaths. In the US, there were 277,205 cases and 6,593 deaths. As of 3/28/2020, there were an estimated 39,000,000 cases of the flu in the US, 400,000 hospitalizations and 24,000 deaths from the flu. See more on my blog.
|9 AM - Noon 2 PM - 5:30 PM
|9 AM - Noon 2 PM - 5:30 PM
|9 AM - Noon 2 PM - 5:30 PM
|9 AM - Noon 2 PM - 5:30 PM
|9 AM - Noon 2 PM - 5:30 PM
The office closes at 4 PM on the first Tuesday of each month.


text:
That's my line, ya goober.
Not my self esteem. :')
What up?
I can believe that!
How good it feels to animate with Flash cs6 instead of Flash 8.
Aw, I feel so special. <3 What's on your mind, Jiggles?
1 Day without talking to you and I miss you already.
I feel honored. Hope you enjoy your vampire mermaid.
Oh no, I just wanted to include your fanart in my RHG page, thanks.
Unfortunately doesn't work in VMs anyways, but just as a heads up, you will have to remove the star.


text:
A fire swept through a hotel early Friday in a resort in the northern Philippines, killing seven people.
Two Americans, one South Korean and another foreigner whose nationality is yet to be established are among the dead, the owner of the hotel, David Fischer, said by phone. Authorities had initially suggested three Americans were believed to be among the dead.
Fischer said the fire began around 2 a.m. local time on the ground floor of the Dryden Hotel, which is in a nightlife district of Olongapo City, the site of a former U.S. Naval base situated west of the Philippine capital, Manila.
The flames destroyed seven bedrooms, as well as a set of offices, a communications center and a computer room, he added.
The seven victims were all killed by smoke inhalation, according to Fischer, five of them in their rooms and one in the process of trying to escape.
Investigators are still looking into the cause of the blaze, but Fischer said initial signs suggested it may have been an electrical fire.
Police are trying to identify the victims' remains, as their identification documents were burned in the fire, said a local fire investigator, Jose Borlagdatan.


text:
Filed Under (Harley Davidson) by admin on 10-04-2011
Models Kit 50227-01 is designed for forward controls and fits: •1989 and later FX Softail Models with Original Equipment (OE) Forward Controls, •1993 through 2002 FXDWG, •Dyna models equipped with Forward Control Kit 49080- 93 or 49080-93A. Kit 50227-01 does not fit Dyna models equipped with Forward Control Kit 49080-03 or Forward Control Footrest Support 33695-03 (left) or 33697-03 (right). Kit 50236-01 is designed for mid controls and fits: •all 1990 and later Dyna Model Motorcycles with Original Equipment (OE) Mid Controls. Additional Parts Required Proper installation of this kit also requires installing a pair of Heel Rest Pegs, or Shifter Pegs, which can also be mounted as heel rests. Refer to the appropriate Parts Catalog for stock shifter pegs, sold separately. The current Harley-Davidson Genuine Motor Accessories and Parts catalog also has a selection of Heel Rest Pegs or Shifter Pegs and matching Footpegs. Any shifter peg style that is symmetrical in design can be used as a left or right side heel rest. The rider's safety depends upon the correct installation of this kit. Use the appropriate service manual procedures. If the procedure is not within your capabilities or you do not have the correct tools, have a Harley-Davidson dealer perform the installation. Improper installation of this kit could result in death or serious injury. (00333a) NOTE A Service Manual for your model motorcycle is available from a Harley-Davidson Dealer. Kit Contents See Figure 1 and Table 1. INSTALLATION NOTE See Figure 1 for the following procedure. 1. Remove the screw (B), lock nut (C) and spring washer (E) securing the left footpeg to the footrest support bracket (A). Save the hardware for later installation. NOTE Heel rest levers are side-specific. Levers mount so the set screws are on the underside. 2. Obtain a Heel Rest Peg or Shifter Peg (D) (purchased separately) and the left side heel rest lever (3). Apply Loctite® 243 (7) to the threads of the peg and install it to the left heel rest lever. 3. Obtain the screw (B), spring washer (E) and lock nut (C) removed in step 1, and the heel rest lever and peg assembly (D). Position the lever assembly to the desired angle on the mount, and slide the lever assembly with the spring washer into the footrest support bracket as shown. NOTE Splines on the lever and mount provide for a limited range of heel rest angle adjustment. For Kit 50227-01. The heel rest lever (3) can be adjusted after the mount (1) is attached but before the set screw (2) is installed. Slide the lever inward off the spline, and rotate it to the desired angle. For Kit 50236-01. The heel rest lever (3) angle cannot be adjusted after the mount (1) is attached without removing them from the footrest support bracket (A). Check to ensure the heel rest (D) is in a comfortable position before tightening the mounting hardware. 4. Install the original screw (B) and lock nut (C) to secure the heel rest assembly to the footpeg mount. Tighten to 33 ft- lbs (45.6 Nm). 5. Obtain a screw (6), spring washer (5) and nut (4) from the kit. Install the footpeg to the heel rest assembly and tighten to 33 ft-lbs (45.6 Nm). 6. Obtain a set screw (2) from the kit. Apply Loctite® 243 (7) to the threads, and install the set screw to the heel rest lever. Tighten to 16 in-lbs (1.8 Nm). 7. Perform Steps 1 through 6 for the right side. USE


text:
The U.S. Environmental Protection Agency and the National Oceanic Atmospheric Adminstration have approved a 15-year program by the State of California to control polluted water that runs off contaminated sites into streams, rivers and the Pacific Ocean.
California's Nonpoint Source Pollution Control Program, which is the first program in the nation to receive full federal approval as a joint nonpoint source program, targets contaminated runoff from city streets, farms, timber operations and abandoned mines. The plan meets the requirements of the Coastal Zone Act Reauthorization Amendments of 1990 and the Clean Water Act.
"We commend California for taking responsibility to address what is now the leading cause of water pollution through this program and the funding they have committed to improving the program," said Felicia Marcus, EPA's Pacific Southwest regional administrator.
EPA also awarded California $10.6 million to implement the program. Half of the money will support community-based watershed protection projects; another portion will help complete and implement coastal runoff programs. California plans to spend up to $300 million in state and federal funds over the first five years of the program.
Polluted runoff is the leading cause of water quality problems in California--54 percent of California's impaired waterways are polluted by runoff, according to the EPA. In 1998, California experienced at least 5,285 beach days affected by closures and advisories due to poor water quality. The top causes of contamination in California rivers are farming, logging, urban runoff and mining.
(Source: Environment News Service)


text: Please fill out the form below to request your trip discount. Name *FirstLastEmail *Which trip are you interested in? *Rainbow Reykjavik Winter PrideNew Years Eve PackageBears on IceOtherComment or MessagePlease confirm *Yes, please add me to your newsletter for the best LGBT travel tips, news and exclusive discounts. Don't worry, you can unsubscribe at any time.No, thanks. I'm sure your emails are cool but please don't subscribe me to your newsletter. EmailSubmit


text:
The field of journalism is changing to meet the demands of today's evolving media. Cedarville's new and cutting-edge journalism program is designed to equip the next generation of journalists who will bring a strong ethical and moral perspective to the changing way people access the news.
Cedarville's approach: convergent journalism. Full convergence involves a radical change in approach and mindset among journalists and their managers. It involves a shared assignment desk where the key people and the multimedia assignment editors assess each news event on its merits and send the most appropriate people to the story. Convergent coverage is driven by the significance of the news event. Depending on variables unique to each country and company, convergence is one of the most likely scenarios for media organizations around the world.
Cedarville's journalism curriculum is benchmarked with other programs of excellence, and delivers the integrity of a Christian worldview unique to Cedarville University.
Be sure to take a look at our student newspaper, Cedars, to experience a taste of our current students work.
Follow journalism professor Jeff Gilbert's blog about journalism and journalism education.Sample 4-Year Plan Requirements


text:
All hate crimes and incidents should be reported. By reporting incidents, you will enable the police, local councils, housing associations etc to build up patterns of behaviour locally, and highlight areas of concern within your community.
But more importantly, you can get the support you may need and help ensure that offenders are brought to justice and cannot do the same to other people.
Hate crimes and incidents hurt; they can be confusing and frightening.
By reporting them when they happen to you, you may be able to prevent these incidents from happening to someone else. You will also help the police understand the extent of hate crime in your local area so they can better respond to it.
Reporting makes a difference - to you, your friends, and your life.
There are several ways you can report a hate crime, whether you have been a victim, a witness, or you are reporting on behalf of someone else:
You can report any incident you believe was motivated by hostility based on your:
These incidents may involve physical attacks, verbal abuse, domestic abuse, harassment, damage to your property, bullying or graffiti.


text:
TrekDesk Treadmill DeskA treadmill desk from TrekDesk (treadmill not included) lets you walk at work and improve your health, productivity and mood. Trekdesk Treadmill Desk fits virtually any treadmill allowing employees/students to walk slowly while working without sweating or extra time out of the day. Walking promotes health, weight loss, and disease prevention; boosting mood, productivity, and cognitive functions at any age.
Click for Hundreds of Customer Testimonials:"What a great idea ... wish I'd thought of it! This product has been great. I set it up in 30 minutes and within a few hours I had logged a few miles while emailing
and talking with clients on the phone." - Shroder001 (Amazon.com-5 Stars)


text:
Chris29 brauchte ein neues Logo Design und hat einen Wettbewerb auf 99designs gestartet.
Aus 35 Designs von 12 Designern wurde eine Gewinner gewählt.
So Act Network!
About So Act® Network, Inc.
So Act® (OTCBB:SOAN) is a leading provider of private-labeled social networks and social media marketing services. Endorsed by William Shatner as "a ray of hope amidst all the gloom," So Act® is on a mission to acquire and develop a network of cutting edge technologies and social media based products that are geared to simplify and improve peoples lives while making a positive social impact on the world. The founders of So Act are driven by their passion that it is truly possible to make a profit while also making a difference. Learn more at http://soact.org
Think of So Act like a parent company that owns a bunch of smaller companies, products and services. The target market for those smaller companies is mostly social media, technology, etc. But So Act Network needs to come across more as an established brand with a Fortune 500 company look and feel. The target audience for So Act is primarily Investors and Business Owners
Here is what we need specifically.
A New Logo for So Act Network to be used at http://soact.org and on all of our print material, business cards, etc.
The logo should read:
So Act®
The registered symbol should be small and discrete. It needs to be there legally but it should barely be noticeable.
This logo also needs to be used for our Facebook Fan Page, Twitter Account, YouTube Account, and so on. Therefore if you can show multiple versions of the logo it will help most.
Be sure that the logo is in transparent form, so that it can be used on any background.
The logo should symbolize business success with a social cause driven feel to it. It should also symbolize the idea of change.
I am attaching several of our old logos so that you can see the transition that has been made and we are looking for something much better than our in-house designs.
In terms of sizes, we need the logo to be sized for multiple mediums, including website logo, business cards, facebook, twitter, etc.
Thank You in Advance!
Finden Sie heraus, wie ein Designwettbewerb funktioniert, oder lernen Sie mehr über unsere Logo-Design-Angebote.


text:
Are your baby play mats non-toxic? Do they contain any heavy metals, pthalates or other nasties?
- Firstly, we take the safety of babies and children incredible seriously. We developed our own baby play mats with this in mind, after we were very unhappy with the strong chemical smell of other products we purchased for our own children that were made of PVC and EVA
- Our Munchkin & Bear baby play mats are made from PU (polyurethane) and are certified as non-toxic
- The use of PU (polyurethane) compared to PVC (polyvinyl chloride) creates a safer play mat for your children, without the harmful and toxic chemicals, however still allows for a durable and hard-wearing mat which can be easily wiped clean
- They have been independently tested and have passed the European Toy Safety Standards - EN71-1, EN71-2 and EN71-3.
- Additionally, as our baby mats are one solid piece (not puzzle pieces) they won't end up being in your babies mouth being chewed.
Where do you deliver to?
- We deliver within the EU from the UK.
- If you reach checkout and your destination isn't shown please email us on email@example.com and we can investigate the best options for shipping to your country in Europe.
- If you are visiting us from Australia or New Zealand – we can indeed look after you but you need to head on over to www.munchkinandbear.com.au
What is your average delivery time?
- 1-3 working days. Please note some countries in Europe may have slightly longer delivery times (everything is shipped from the UK).
Can I track my order?
- All products are dispatched with a courier and will have a tracking number. When your order is dispatched you will receive an email confirming that your order is on its way
- The dispatch email will give you a tracking number and a link to the courier website so that you can keep an eye on progress
- If you are having trouble tracking your order for any reason please contact us on firstname.lastname@example.com or via our Contact Us page
What are your shipping charges?
- Our aim is to provide the most affordable and reliable shipping we can for all our customers
- Standard weekday shipping within the UK is £6.95
- Saturday delivery (order by 2.30pm Friday) within the UK is £18.95
- European deliveries vary by country but start from £12.50. Exact cost for your country shown in checkout pages.
- If your destination is not shown as an option or you have a question please contact us on firstname.lastname@example.com
Can I order from a non-EU country?
- We currently only ship within Europe
- See here for a dedicated page for non-EU orders including VAT related questions
Can I return my product?
- Yes of course, Munchkin & Bear offers all customers a 100% no questions asked money back guarantee (subject to the terms below)
- We want you to be 100% happy with your purchase. If you change your mind about an item purchased or simply wish to return it, you are welcome to do so for a full refund (less shipping costs). The only conditions applying to returns are as follows:
- All returns must be unused and in their original condition (including all original packaging, labels and straps)
- You must complete your return within 30 days of the date of your order and you are responsible for arranging the return and all related costs
- The original shipping costs to you are not refunded.
- If you wish to return or exchange a product, please contact us at email@example.com and ask for a Returns Form
- PLEASE NOTE: Munchkin & Bear reserves the right to reject returns outside the 30 day return period, or items which are returned that are not in their original condition and/or packaging.
Do you accept stockist enquiries?
- We currently only sell online directly but if you think our product would look perfect in your store please let us know. Please email email@example.com
How can we contact you?
- firstname.lastname@example.com or use our Contact Us form. We would love to hear from you.
- Phone number? Well the reason we don't have a phone number listed on our website is because in addition to running Munchkin & Bear, we are the parents of small children (who save their worst behaviour for when the phone rings :-))
- We endeavour to answer all enquiries within 24 hours however during busy periods it may take a few days - I'm sorry.
Can your baby play mats be ordered in custom colours / can I swap the colours?
- The lead time to produce our baby play mats is around 4-6 months. They are produced in large numbers and unfortunately this makes it impossible to take custom orders or mix and match colours
- We would love to hear your ideas for future designs and colour combinations though - drop us an email on email@example.com
Can we follow you on social media and say nice things about Munchkin & Bear?
- Yes of course! @munchkinandbearuk (ok this isn't a frequently asked question at all, but we do love it when our customers connect with us and share cute pics) You can also tag us using #munchkinandbearuk
What's the best way to clean our play mats?
- Please pop over to see our cleaning tips
Instagram: @munchkinandbearuk
or @munchkinandbear
Facebook: Munchkin and Bear UK
If your question hasn't been answered, please drop us an email at email@example.com (for care & cleaning information please refer to the document you received with your mat or alternatively under the product information on this site)


text:
Hey everyone, here's probably a simple one.
Old water pump (piston pump) blew up so installed a new one.
The pressure switch, factory set to 20/40psi, keeps on bouncing and bouncing causing cycling and eventually the breaker trips.
Pump is primed, delivers water when running.
Before operating I checked the pressure tank pressure and made sure it was at ~18psi.
But the pressure switch still keeps bouncing on off on off etc. trip.
My gut is telling me the bladder is the tank is probably also damaged.
Would you agree with my thoughts?
The height difference between the pump and tank is only about 8-10ft in a 3/4" pipe, so what ~5 or less psi there say...
Any info with your experience, thoughts?
After checks and checks I cheated and held the contacts for a moment to build some pressure, the system had running water for a few minutes and then once P dropped the switch was bouncing again the same.
Set up downstairs:


text:
quicksilver (03-23-2014)
Weekly Fraser Valley Sport fishing column; Feb 3 to 10, 2014
Sometimes, and with the greatest respect, I blame old Fredrick Halford for much of our dullness. No one has ever taken greater pains with exact imitations, not merely of a species of fly but with precision as to sex and state of development. He has harsh words to say about those awful monstrosities called fancy flies even while admitting that they occasionally take fish; and I suspect he would have been heartily ashamed of killing a fish on a light olive in the midst of a hatch of dark olives. Generations of fishermen have followed him The words of Roderick Haig-Brown, discussing the arrogant assumptions of some anglers, in his book, Fishermans Fall.
How often do we miss the mark; by falling into assumption, or by relegating too much credibility into the assumptions of others? Last week we drew attention to the fact that fish have a mind of their own, and cannot be pigeon holed into a set pattern of behavior, no matter how much some would like to believe they can. At first glance this subject may seem juvenile, but I ask you to humor me and look deeper. Often highly successful days of fishing come from looking outside traditional and accepted belief, and applying what would appear unorthodox. Large trophy fish survive and get big, by evading capture. I believe over the seasons they become accustomed to all the popular lures and baits, and learn to operate outside the box. To catch these fish we need to open our minds and think outside the box too.
The Report
Our lower mainland lakes that are not iced over are fishing slow to fair. Concentrate on fishing close to shore, in and around the north east sections of your favorite lake with a slow troll or retrieve from late morning through mid afternoon. Try: Wooly Bugger, Big Black, Micro Leach, Baggy Shrimp, Dragonfly Nymph, or Halfback Nymph. For warm afternoon dry (floating)
Fly Fishing; try: Lady McConnell, Tom Thumb, Griffith Gnat, Black Gnat, Renegade, Irristible or Elk Hair Caddis.
The Fraser River and its back waters are fishing fair to good for Dolly Varden and cutthroat. For Cutthroat try: Professor, Anderson Stone, American Coachman, Rolled Muddler, Black Gnat, Griffith Gnat, Zulu, Hares Ear, Renegade, or Irresistible. For Dolly Varden try: Zonker, Flat Black, Big Black, Eggo, Clouser's Deep Minnow, Bucktail, and Lefty's Deceiver.
The Vedder River is good for Dolly Varden, rainbow, and steelhead. For rainbow try: Czech nymph, Kaufmann Stone, Hares Ear, Big Black, Wooly Bugger, Eggo, Zulu, Soubou, Irresistible, Elk Hair Caddis, Tom Thumb, Black Gnat, or Renegade. For steelhead try: Steelhead Nightmare, Flat Black, Kaufman Stone, Rolled Muddler, Steelhead Bee, Irresistible, October Caddis, or Stimulator.
The Harrison River is good for cutthroat.
Keep your fly in the water
quicksilver (03-23-2014)
There are currently 1 users browsing this thread. (0 members and 1 guests)


text:
PORTLAND, Ore., March 28 (UPI) -- Brook Lopez and Reggie Evans combined to give Brooklyn a rocket-like start Wednesday and the Nets went on to rout Portland 111-93.
Brooklyn led by 20 after the opening period and was not threatened while remaining within 2 1/2 games of New York for the lead in the Atlantic Division.
Lopez scored 28 points and Evans came through with 22 points and a career-best 26 rebounds. Brooklyn outrebounded Portland by 14.
LaMarcus Aldridge had 24 points for the Trail Blazers, who fell for the second straight game and are now 3 ½ games behind the Los Angeles Lakers for the eighth and final playoff spot in the Western Conference.
Brooklyn is 4-1 on an eight-game road trip that lasts through April 3.


text:
5 minutes from Biarritz town center, the market and shops, this apartment offers a beautiful view of the sea. Living and dining rooms opening onto a terrace facing the ocean, 2 bedrooms. Tennis courts and pool in the residence Garage and cellar.
To the fullest extent permissible pursuant to applicable law, this web site and the materials are provided on an "as is" and "as available" basis. LuxuryRealEstate.com expressly disclaims all warranties of any kind, whether expressed, implied, or statutory including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose and non-infringement. We do not warrant that this web site or the materials are completely error free, will operate without interruption, are compatible with all equipment and software configurations, free of viruses, errors, or other harmful components, or will otherwise meet your needs.


text:
0 Items (Empty)
You have not viewed any items recently.
Your shopping cart is currently empty. If you would like to make a purchase today, add items to your shopping cart.
Search Term
Store Home
Sort by: Default A-Z Z-A Price Lowest-Highest Price + Price Highest-Lowest Price - Age + Age -
GEMS: Tree Homes
Grade Pre K-1
GEMS: Treasure Boxes
Grade K-3
GEMS: The Real Reasons for Seasons
Grade 6-8
GEMS: The Rainbow of Mathematics
Teacher Guides
GEMS: The GEMS Leader's Handbook
GEMS: The Architecture of Reform: GEMS and National Standards
GEMS: Terrarium Habitats
Grade K-6
GEMS: Stories in Stone
Grade 4-8
GEMS: Spark Your Child's Success in Math and Science: Practical Advice for Parents
Parent Resources
GEMS: Sifting Through Science
Grade K-2
GEMS: Secret Formulas
Grade 1-3
GEMS: Science and Math Explorations for Young Children
GEMS: Schoolyard Ecology
Grade 3-6
GEMS: River Cutters
GEMS: Penguins and Their Young
GEMS: Parent Partners: Workshops to Foster School/Home/Family Partnerships
GEMS: Paper Towel Testing
Grade 5-8
GEMS: Padres Participantes
GEMS: Only One Ocean
GEMS: On Sandy Shores
Grade 2-4
GEMS: Of Cabbages and Chemistry
GEMS: Ocean Currents
GEMS: Mystery Festival
Grade 2-8
GEMS: Mother Opossum and Her Babies
GEMS: More Than Magnifiers
GEMS: Moons of Jupiter
GEMS: Microscopic Explorations
GEMS: Matter: Solids, Liquids & Gases
GEMS: Math on the Menu
Grade 3-5
GEMS: Math Bundle
GEMS: Math Around the World
GEMS: Living with a Star: From Sunscreen to Space Weather
GEMS: Liquid Explorations
GEMS: Life Through Time: Evolutionary Activities for Grades 5-8
GEMS: Learning About Learning
GEMS: Involving Dissolving
GEMS: Invisible Universe: The Electromagnetic Spectrum from Radio Waves to Gamma Rays
GEMS: Investigating Artifacts
GEMS: Insights & Outcomes: Assessments for Great Explorations in Math and Science
GEMS: Hot Water and Warm Homes from Sunlight
GEMS: Hide A Butterfly
Grade Pre K-K
GEMS: Group Solutions, Too!
Grade K-4
GEMS: Group Solutions
GEMS: Frog Math: Predict, Ponder, Play
GEMS: Environmental Detectives
GEMS: Elephants and their Young
GEMS: Electric Circuits: Inventive Physical Science Activities
GEMS: Eggs Eggs Everywhere
GEMS: Early Adventures in Algebra: Featuring Zero the Hero
Grade 1-2
GEMS: Dry Ice Investigations
GEMS: Discovering Density
GEMS: Crime Lab Chemistry
GEMS: Convection: A Current Event
GEMS: Color Analyzers
GEMS: Chemical Reactions
GEMS: Buzzing A Hive
GEMS: Build It! Festival
GEMS: Bubble-ology
GEMS: Bubble Festival
GEMS: Aquatic Habitats
Grade 2-6
1 | 2 [65 Items / 2 Pages]
Lawrence Hall of Science at 1 Centennial DriveBerkeley, California 94720-5200United States
© 2020 the Regents of the University of California. All rights reserved worldwide.


text:
Gawker Media boss Nick Denton is "rationalizing" his blog business by spinning off three underperforming sites: Wonkette, Gridskipper and Idolator. The sites will find new homes/owners as follows:
- Wonkette: Current editor Ken Layne will take over the political site, in conjunction with ad network Blogads.
- Gridskipper: Former Gawker manager Lockhart Steele will absorb the travel site into his Curbed network; Denton is one of Steele's investors.
Idolator: The music site is going to Buzznet, the music site which says it doesn't want to roll up other music blogs, but seems to do so, anyway. This was the last of the three deals to be finalized, which apparently happened over the weekend.
"There's a cold wind coming," says Denton, via IM. "We need to focus on our core titles." The move will leave Denton with 12 sites, including science fiction site io9, launched in January
Denton wouldn't release financial details but says they're "not material" -- i.e. he's more or less giving the sites away. In some cases an earnout clause could eventually give Denton a few more bucks if the sites do well. We don't know details about which editors and writers are staying or going. "We're hoping that the site leads at very least will all be retained," Denton says. Internal e-mail from Denton to Gawker staff follows post.
Denton's move to shed Gridskipper and Idolator isn't surprising: Those two are Gawker Media's lowest-performing sites, clocking in around 1 million page views a month. Idolator had reportedly been on the block last year, and we noted then that Gridskipper might be a sale candidate as well.
Wonkette is a different story: It was one of Denton's earliest success after launching Gawker, and continues to generate traffic: In March it logged 5.8 million page views, a record for the site. But it's never reclaimed the buzz it had under founding editor Ana Marie Cox, now a freelancer for Time Inc. More important, Denton's sales team had trouble moving inventory; political blogs are tough sells to begin with, and Gawker Media specializes in consumer electronics and entertainment brands.
The big picture: You can interpret this two ways. Either Denton is dumping three weak sites to concentrate on his strong ones, or he's worried about the online ad market in the face of a looming recession. Denton is happy to provide both spins.
The "look out!" take: "I'm not so sure that an advertising recession will spare the Internet," he says. "And, if there's a chill coming, I'd rather be stocking up on firewood."
And the "things are going great!" take: Denton says that his 15 sites generated 227 million pageviews in March, up 96% y/y; uniques are 29.7 million, up from 22 million six months ago.
How about a nice middle ground? OK. How about this one, from 2006 -- the last time Denton "rationalized" some of his sites. NYT:
"We are becoming a lot more like a traditional media company," Mr. Denton said last week. "You launch a site, you have great hopes for it and it does not grow as much as you wanted. You have to have the discipline to recognize what isn't working and put your money and efforts into those sites that are."
See Also:Blog Mogul Denton's Reward To Valleywag Drones: 33% Pay Cut
Gawker Media Peddling Idolator Music Site?
Internal email from Denton:
From: email@example.com
Subject: Gawker spinning off three sites -- Idolator, Gridskipper and Wonkette --
Date: April 14, 2008 10:26:06 AM EDT
To: firstname.lastname@example.com, email@example.com
I'm amazed we've managed to keep a lid on this news; that, given your
naturally gossipy natures, must be a first! We're spinning off three
sites: Idolator, Gridskipper and—this one may be a surprise—Wonkette.
There were indeed some rumors about Maura Johnston's music blog late
last year; they were true of course. For reasons that I'll explain
below, both it and our travel and politics sites have better
commercial futures outside Gawker than within. (Excuse the corporate
lingo: some of it is unavoidable.) But, first, the facts, which will
be hitting the wires later this morning, or as soon as you leak this
email. Go ahead!
* IDOLATOR is going to Buzznet, a music-focused web and social
network. Buzznet recently acquired Idolator's chief rival, Stereogum,
and received a big investment from Universal Music Group.
* GRIDSKIPPER isn't going far: it's being taken over by Curbed, the
network founded by Lockhart Steele, in which Gawker Media is a
* WONKETTE is being spun off to the managing editor, Ken Layne, former
founder of one of the web's very first news sites, Tabloid.net. The
title will become part of the Blogads network of political sites,
which includes Daily Kos, among others.
Why these three sites? To be blunt: they each had their editorial
successes; but someone else will have better luck selling the
advertising than we did.
Music audiences are fragmented across genres; Maura's Idolator gave
Stereogum a good run, but a group with a whole array of music sites
will command more attention from record labels than we could. In the
case of Gridskipper, our urban travel guide, we could never match
Curbed in attention to city-specific content and advertising. As for
Wonkette: political advertisers are a strange breed; they don't come
through the same agencies our sales people deal with.
I'm relieved we've found pretty decent homes for the three sites, and
most of their writers, but we're gutted to lose them. Idolator's Pop
Critic's Poll was a tremendous coup—and Patric's bleeding-heart logo
for the site was one of my favorites. Gridskipper is so far the most
sophisticated travel blog: it entirely deserved its inclusion in
Time's list of the 50 coolest websites.
And Wonkette is one of the brands with which the company is most
associated; people will be shocked that we would ever part with it.
The political site has won an array of Bloggies and other awards; it
introduced the word ass-fucking into the dictionary of political
abuse; the founding editor's slippers are even on display in the new
media museum in Washington, DC. And Ken and his team have brought a
new liveliness to the site this election season—validated by the
record traffic of the last three months.
So why not wait, at least till the election? Well, since the end of
last year, we've been expecting a downturn. Scratch that: since the
middle of 2006, when we sold off Screenhead, shuttered Sploid and
declared we were "hunkering down", we've been waiting for the internet
bubble to burst. No, really, this time. And, even if not, better safe
than sorry; and better too early than too late.
Everybody says that the internet is special; that advertising is still
moving away from print and TV; and Gawker sites are still growing in
traffic by about 90% a year, way faster than the web as a whole. But
it would be naive to think that we can merely power through an
advertising recession. We need to concentrate our energies, and the
time of Chris Batty's sales group, on the sites with the greatest
potential for audience and advertising.
The dozen sites that remain represent some 97% or our 228m pageviews
per month, and an even higher proportion of our growth and advertising
revenue. (Key facts are below, in case anyone asks.) We'll be able to
devote more attention to breakouts such as Jezebel and io9, as well as
established titles such as Gizmodo and Kotaku, which are becoming
utterly dominant in their domains. And, then, once this recession is
done with, and we come up from the bunker to survey the internet
wasteland around us, we can decide on what new territories we want to
Both Noah and I are around to answer any questions. On email, IM, or
phone. I'm xxx-xxx-xxx and Noah is on xxx-xxx-xxxx.
* A dozen sites, Gizmodo first launched in August 2002, most recent,
io9, in January 2008
* Gawker, Gizmodo, Kotaku, Lifehacker, Jalopnik, Deadspin, Defamer,
Jezebel, Valleywag, io9, Consumerist, Fleshbot
* A record 18 "Bloggie" nominations in 2008, way more than any other
blog collective (one of those was for Idolator)
* Audience of 29.7m unique visitors a month for the whole network, up
82% at annualized rate (http://www.quantcast.com/p-d4P3FpSypJrlA)
* Each individual site has at least 1m uniques or, in the case of io9, soon will
* Pageviews of 227m in March -- 219m if you take out the three sites
being spun out -- up 89% on a year earlier (Sitemeter)
* For those who measure these things, Gawker is the web's leading
independent blog group