The following are the contents of an actual email that I received this afternoon:
I have a very hot Java Developer rek with a direct-client in Manhattan. Please send me candidates with rates and contact-numbers.
Interviews this week.
I would be shocked if Priya lands any candidate this year.
Let's dissect all of the ways that this email is completely ineffective:
I am a .Net developer. I know Java and worked with it for 4 years on college, but I have not worked with it in any sort of significant capacity since then. Assuming this email was generated based on my profile on either Dice or Monster, you'd think that the recruiter would attempt to filter the candidates...
"Hi cchen"? Why am I being addressed by my email account name? I'm pretty sure that I have my name listed on Dice and Monster. If this were to have come from some third party database somehow, wouldn't it make sense to just use something like "Good afternnon,..."?
"rek"? Take some time and type out the extra keystrokes and spell it out. A little professionalism goes a long way.
No. I am not doing your job for you.
Contrast this with another email from a Bradley G.:
My name is Bradley and I'm an IT recruiter at [XYZ]Technologies Corporation. Our records show that you are an experienced IT professional with experience in .NET. This experience is relevant to one of my current openings.
The opening requires ASP in addition to the above skills.
It is located in Pittsburgh, PA.
If you are qualified, available, interested, planning to make a change, or know of a friend who might have the required qualifications and interest, even if we have spoken recently about a different position. You may also send me an e-mail with a copy of your current resume. If you do respond via e-mail please include a daytime phone number so I can reach you. In considering candidates, time is of the essence, so please respond ASAP. Thank you.
If you are not currently seeking employment, or if you would prefer I contact you at some later date, please indicate your date of availability so that I may honor your request. In any event, I respectfully recommend you continue to avail yourself to the employment options and job market information we provide with our e-mail notices.
Much more professional and much more likely to actually attract a candidate, but it still gets a few items wrong:
- I did not apply for any job. It would have been better to use use a simple greeting like "Good afternoon" or "Greetings" or perhaps even something creative like "Hello from IT land!"
- I would have added "please responsd ASAP"...seems like a bad sales pitch.
Just some random afternoon ranting...
In trying to wrap my head around how solutions should be designed and componentized in SCSF/CAB, I've spent a bit of time trying to study up on Model View Controller (MVC) and Model View Presenter (MVP).
The packaged documentation, in my opinion, doesn't necessarily do a good job of covering these two topics and the variations of MVP that really make sense in CAB.
One of the best resources for discourse on these two topics is Martin Fowler's article on GUI Architectures, which provides a broad view of three of the most common underlying architectural choices for many of the GUIs that we work with today.
What I've observed is that PV is more "aligned" with the design of the components in CAB than SC, which Fowler summarizes:
The separation advantage is that it pulls all the behavioral complexity away from the basic window itself, making it easier to understand. This advantage is offset by the fact that the controller is still closely coupled to its screen, needing a pretty intimate knowledge of the details of the screen. In which case there is a real question mark over whether it's worth the effort of making it a separate object.
In my opinion, since the CAB generated presenter isn't coupled with a concrete implementation of the view, PV is the way to go since this will allow a lower level of coupling with the concrete implementation of the view. I went about this by adding interface methods to return Control (one could go as generic as Object as well) instances from the view which would then be rendered, wired, and databound by the presenter. In other words, it's not really Model View Presenter as the documentation would have you believe.
Regardless, this allows a great deal of flexibility in the design of the module as a whole as the view can truly be replaced completely independently of the presenter since the presenter is only coupled with the interface class. In addition, it allows for easy replacement of data visualization types using the adapter pattern to connect data to the control type (for example, having one adapter if the returned control is of type TreeView and another when the control is a DataGridView).
However, an even better description of the architectural intent of CAB modules is Humble Dialog, a pattern formalized by Michael Feathers. What Feathers terms "smart object" is congruent to the presenter, which "pushes data onto the view class" through a view interface. The view, of course, is the actual UserControl derived view class. Now this leaves a key question: what is the place of the model in such a pattern? Does it have a place? With SCSF (but not necessarily with CAB when used with desktop applications), the classic sense of the model almost has no place in such an architecture; the model is but a dumb container for data. It leaves you with what Fowler terms an Anemic Domain Model, an "anti-pattern":
The basic symptom of an Anemic Domain Model is that at first blush it looks like the real thing. There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is hardly any behavior on these objects, making them little more than bags of getters and setters. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data.
While Fowler views this pattern with disdain, I can't help but wonder whether it is the most natural choice for a smart client style application which should rely heavily on service layers to handle the data models. Otherwise, it would seem that one would end up writing a great deal of domain objects which were nothing more than shells (well, perhaps this is still useful if complex service interactions are necessary) which make the calls through the service proxies.