Show Posts |
Pages: [1] 2 |
1 |
Programmers Corner / Ruby / Re: Writing a Searchable Dictionary with Ruby and wxWidgets |
on: August 31, 2007, 10:07:29 AM |
I received an e-mail today about this article that alerted me to some changes to wxRuby since I wrote this article (over a year ago! How time flies).
The most breaking change is that wxRuby, for reasons known but to God, changed the header name from 'wxruby' to 'wx'. Thus, the code should now read
require 'wx'
The sample code distributed with the latest wxRuby package is a good place to start. I noticed that they do some fairly fancy stuff with RubyGems:
begin
require 'wx'
rescue LoadError => no_wx_err
begin
require 'rubygems'
require 'wx'
rescue LoadError
raise no_wx_err
end
end
include Wx
That code will automatically install the wxRuby library if it's not installed. To install wxRuby manually, you can just type
gem install wxruby
Of course, both of these methods assume that RubyGems is installed (if not, well, why not?).
I also noticed that the close button on the dialog no longer seems to work! I don't know why this is, and I haven't really had the time to find out, but it means you need to ctrl+c it if you want to close the window. Doh.
It's nice to see ruby libraries progressing along, though sometimes you have to wonder if they couldn't have just aliased 'wxruby' to 'wx' so code that requires 'wxruby' doesn't start breaking
Ruby is a great language, and having completed a decently large project in Ruby at the end of last year, I believe I can say that the arguments claiming it doesn't scale are simply false. Its elegant syntax and ease of readability make it actually easier to maintain, and so long as you follow proper software engineering principles like encapsulation and separation of concerns, I believe that rubya is at least as viable a language as the more enterprisey offerings like C# (and when Microsoft releases its implementation of ruby for the .NET framework, we'll have the best of both worlds ).
Enough ruby evangelizing. Let's get coding!
|
|
|
2 |
Programmers Corner / C# / Re: Building a Plugin Architecture with C# |
on: July 27, 2007, 04:32:14 PM |
Sure, I'm always glad to help out a fellow coder. If you want to discuss this further, feel free to do so.
Good luck,
Nathan
|
|
|
3 |
Programmers Corner / C# / Re: Building a Plugin Architecture with C# |
on: July 26, 2007, 06:13:13 PM |
My copy of InterfaceDefinitions.cs has the reference to System.Runtime.InteropServices, but the one on the site doesn't. I don't know whether I sent in an old version of the code with the article or what. Thanks for noticing that.
Your question is a little bit tricky. A lot of it depends on what sort of interdependency exists between the plugins.
We're talking about what can be thought of as a service-oriented architecture. You have a bunch of plugins which provide services, some (perhaps all) of which are known. From the perspective of the host application, it has needs/requirements which must be met, and the plugins provide services to meet these needs. How it meets those needs is not something it should be concerned about, so long as those needs are met.
If a plugin (a service) itself has needs that must be met, it in turn can become a host. So a math plugin could load a storage plugin DLL directly, without the intervention of the application which loaded the math plugin.
Now let's say that the math plugin doesn't want just any storage plugin, it wants the one that the host is using. This is fine.
A lot of times in the real world, your components will be pretty tightly knit. In the software engineering world, there is a distinction made between coupling and cohesion. Coupling is bad, cohesion is good. An example of tight coupling would be if you had a storage plugin which used an array. If the host application got a reference to that array and passed it to the math plugin, all of a sudden you are very tightly coupled. The storage plugin cannot change its internal implementation (changing from a stream to a linked list, for example), because that would break the host and the math plugin. The host cannot change storage plugins, because the new one might not use an array, or math plugins, because the new one might not know how to handle the array correctly (or at all).
Cohesion, however, is where one feature is used by all parts of the application rather than being reimplemented. Having the host use a storage plugin, then reading the data from that plugin into an array, then passing that array into a math plugin, then having the math plugin store the data in a different storage plugin would be poor cohesion. However, using a storage plugin and passing a reference to that plugin to the math plugin would be good cohesion, so long as that functionality is shared across all math plugins.
That last part is in italics because it's important. This is what interfaces are all about. If there is a "setStorage" method in the interface, then for the host application to pass a reference to the storage plugin is very appropriate (if only one instance of the math plugin uses the storage plugin, you have actually created a new plugin type. Define a new interface called IMathUsingStoragePlugin or something equally cumbersome, inherit from IMathPlugin, and use that instead).
What should happen in this case is that the storage plugin belongs to the host. It then passes a reference to this plugin using the IStorage interface to the math plugin, which has a method to accept it. Let's look at some code:
public interface IMathPlugin: IPlugin
{
void SetStorage(IStoragePlugin storage);
double Add(double a, double b);
double Subtract(double a, double b);
double Multiply(double a, double b);
double Divide(double a, double b);
};
So here we have a new method on IMathPlugin: SetStorage. Now when we load our math plugin, before it can do anything useful, we need to load a storage plugin. Then we pass the IStoragePlugin into the math plugin, and it works.
Why is this good rather than bad? This is good because we are using interfaces. We have not violated encapsulation or introduced coupling, because you can still change storage plugins at will. All that is required is that you have a storage plugin of any type before you use the math plugin, which is OK because that's already a requirement, given your specification.
In case you are still confused, let's look at the example of a media player that uses plugins. You have a SoundReader plugin that can read different types of audio, and you have a VideoReader plugin that can read different types of video. The sound reader and the video reader both have methods (similar to the version and author methods in my code) that say what types of formats they can handle. Well, let's say we have a container format, like Matroska (mkv). Let's create a new ContainerReader plugin type. This type is given the media file, and it parses it and determines that it needs, say, a VideoReader than can handle compressed h.264 video and a SoundReader that can handle compressed ogg audio. The media player looks through its available plugins, finds the appropriate readers, and passes them in. This is good cohesion since the matroska reader doesn't have to reimplement reading ogg and h.264, while it's not heavy coupling, since it just uses the interfaces and makes no assumptions about the internals of the two reader classes.
I hope this long post makes sense, and if it doesn't then feel free to ask me for clarification.
Nathan
|
|
|
4 |
Programmers Corner / C# / Re: Building a Plugin Architecture with C# |
on: July 25, 2007, 06:09:23 PM |
Hi kaosd,
I'm really glad you were able to get some good ideas from what I wrote. I still get e-mails about this article (yes, over a year after I wrote it), so obviously it's still an important topic.
Thanks for writing!
Nathan
|
|
|
5 |
Programmers Corner / PHP / Re: Introduction to Image Manipulation in php + GD |
on: February 19, 2007, 09:44:46 AM |
Hi, Brian,
What you are talking about is called hotlinking, and as you say, is a problem.
Generally, this problem is solved in the server configuration rather than in code. Not only is this a more robust solution, it prevents the php engine from even being invoked, saving your CPU cycles.
The traditional approach is to use .htaccess or your httpd.conf file (assuming you're using Apache) plus URL rewriting rules. For a full discussion of this topic, try here or here. Both of these sites assume you're using Apache. If you're not, you will have to adapt the instructions to whatever web server you're using (or switch to Apache, which might be the better option ).
I hope this fits your needs.
Nathan
|
|
|
6 |
Programmers Corner / Other programming languages not listed here / Creating a Multi-Language, Serverless Chat Program - Part 1 |
on: October 26, 2006, 09:54:06 PM |
I hope so.
I was all ready to send off the part 2.1 (client) document, and then I decided that I would finish writing the application to make sure that there weren't any client changes that were needed. It would be kind of confusing to have to change things in mid-project. But I've just been so swamped with work that I haven't had time to complete and test the code yet--it's about 85% done, and hasn't been touched in two or three weeks. I hope to put forth a major push on it this weekend, though I'm also doing a major push on another project as well (one that actually has a due date ;) ).
The good news is that, when I finish writing the application, most of the work for part 2.2 (server) will be done. All I'll need to do is prepare the document, which just takes a few hours. So even though the wait between 1 and 2.1 is getting close to...what is it, two months? geez, the wait between 2.1 and 2.2 should be about a week or two.
I will also entertain suggestions for other languages. I haven't decided yet which language to use next...I'm debating between Ruby and C++, though if there's demand then Python or Java are also possibilities.
Look forward to it!
|
|
|
7 |
Programmers Corner / Other programming languages not listed here / Creating a Multi-Language, Serverless Chat Program - Part 1 |
on: October 09, 2006, 08:27:41 PM |
For those still waiting for part 2, don't worry...it's coming! I was on page 14, when I thought to myself "you know, there's no way I would have the attention span to read through all this, and I wrote the durned thing!". So I'm splitting it into two parts.
Believe me, it will be worth the wait!
Nathan
|
|
|
8 |
Programmers Corner / C# / Building a Plugin Architecture with C# |
on: October 09, 2006, 08:23:37 PM |
I'm glad you enjoyed the article and got your questions answered! If you have any more, feel free to ask.
Thanks for reading and commenting!
Nathan
|
|
|
9 |
Abetment / Site Suggestions / Code Syntax Highlighting |
on: August 11, 2006, 01:11:24 PM |
Mainly the colors. When I use a syntax-highlighting editor, I keep the colors fairly muted (no orange :) ), and all part of the same color "family" (blues and greens, mainly). I can live with the current scheme, though, if it's not too changeable.
It would be cool if users could define their own scheme that they like and then it gets saved in a cookie.
|
|
|
10 |
Abetment / Site Suggestions / Code Syntax Highlighting |
on: August 11, 2006, 09:10:41 AM |
Says that it will do syntax highlighting for "text"...I wonder what sort of syntax it will highlight. The scheme might take some getting used to, but it's not bad.
|
|
|
11 |
Programmers Corner / PHP / Introduction to Image Manipulation in php + GD |
on: August 07, 2006, 02:40:15 PM |
By the way, this article doesn't appear in the PHP section of the main page. Just FYI.
|
|
|
12 |
Programmers Corner / PHP / Introduction to Image Manipulation in php + GD |
on: July 30, 2006, 05:24:22 PM |
Actually, one of the cool things about this script is that it doesn't create a file on disk at all. The image is resized in-memory and sent directly to the browser.
Creating a permanent file would be a security hole, because it would allow an attacker to request an effectively infinite (actually combinatorial) number of files to be created, which in the worst case would fill up your disk or exceed your quota.
If you read the source I included, you will also see that I didn't talk about the Autoscale algorithm in the tutorial. It's fairly simple, but it's just math and not really interesting material for an online instruction guide. However, I will be glad to answer questions about it if the code isn't clear.
|
|
|
13 |
Abetment / Site Suggestions / Request for printable articles |
on: July 24, 2006, 07:30:49 AM |
Hah, your DTD already claims that you are xhtml ;).
|
|
|
14 |
Abetment / Site Suggestions / Request for printable articles |
on: July 21, 2006, 04:29:45 PM |
I got an e-mail from one Gary Blomquist, who apparently was under the impression that this was my site :roll: . Anyway, I will reproduce it here verbatim:
Nathan,
Would you consider modifying your web site to render a printable version of your articles? I wanted to print the WxRuby article but don't see a nice way to do it. I tried pasting it into Word but it doesn't look very nice.
Thanks,
Gary Blomquist
Kevin, I redirected him here, but I don't know if he'll make it or not, so I'm going ahead and making the request for him. Thanks.
|
|
|
15 |
Programmers Corner / C# / Building a Plugin Architecture with C# |
on: June 27, 2006, 07:31:35 PM |
Phil over at You've Been Haacked expands on this topic and presents an architecture that attempts to avoid versioning issues.
He accomplishes this by having the host expose events. These events act as messages to the plugin. The host calls a single Init method on the plugin, allowing the plugin to subscribe to host events (or not, as the case may be). Thus, the plugin itself is essentially declaring which events it cares about, while all (well, almost all) of the interface work is done by the host, rather than the client. His example relies on the fact that classes are reference types and are implicitly passed by reference in C#, thus the "e.IsSpam = true" line is in effect sending a message back to the host application.
This approach does not make plugins completely resistant to versioning. For example, if a certain event becomes obsolete, it has to be kept around so that it doesn't break old plugins that rely on the presence of that event. It also moves the interface dependency away from the plugin interface but into the argument interface--you will still hit versioning problems if you decide to alter the IsSpam field.
Ultimately, I think his approach does not offer enough benefit to make up for the increase in complexity and loss of discoverability caused by abandoning the traditional interface definition method for something fancier. I'm glad it works for him, and it may work for you too, but what he offers still suffers from enough versioning issues that I wouldn't declare the problem as solved just yet.[/url]
|
|
|
|