November 2003 - Posts

Anemic Domain Model

Martin Fowler notes:

“This is one of those anti-patterns that's been around for quite a long time, yet seems to be having a particular spurt at the moment. I was chatting with Eric Evans on this, and we've both noticed they seem to be getting more popular. As great boosters of a proper Domain Model, this is not a good thing.

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 very little behavior on these objects. 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....

...I don't know why this anti-pattern is so common. I suspect it's due to many people who haven't really worked with a proper domain model, particularly if they come from a data background. Some technologies encourage it; such as J2EE's Entity Beans which is one of the reasons I prefer POJO domain models.” [1]

IMO, the reason for this is pretty simple. This is no different than what we have consistantly seen with web app development. As soon as a technology starts to reach a critical mass, all the morts jump in and the average quality of design work begins to decrease (it doesn't help that VS.NET now makes creating these types of apps easy enough for the brain dead). When web apps started getting popular, we had to constantly tell people “Don't put business logic in your UI layer!” (and indeed, we still have to do this every once and a while). With SOAs, the new UI layer is the service layer. I assume more and more of the same design problems will begin to crop up in SOAs as they become more and more popular.

[1] Anemic Domain Model. http://martinfowler.com/bliki/AnemicDomainModel.html

 

 

Posted by Jesse Ezell with no comments

Whidbey Security Flaw (MembershipUser)

Revisiting the MembershipUser class, there is something that has perplexed me since day one. Why is there not a UserID associated with it? The simpleton might respond, “but is has a Username property and those are gaurenteed to be unique!” To which I would respond, “yes, until 'jsmith' is fired then another 'jsmith' comes along, you add him to the DB, and now any tables that referenced his username have all of the old 'jsmith''s data.” Of course, some of this can be solved by adding events to the base Membership providers (such as “UserDeleted”), so that you can actually remove user data from the DB if someone deletes them (which should probably happen anyway...), but that requires the user handling those events. If we want things “secure by default,” the solution is to give a proper ID in the first place that will continue to be unique (under AD, you can get the “objectSid” prop, in SQL it will most likely be an identity field or GUID).
Posted by Jesse Ezell with 3 comment(s)

Designing Quality Frameworks

A few tips...

 

  1. The most important thing to remember when designing APIs and frameworks is that you must know your subject area. Deep within the heart of every developer lurks the temptation to just “start coding” and “let it come to you.” While highly skilled developers may still end up with a working framework, very few developers can create a usable framework this way. Dealing with the grey areas inside your class hierarchies will be time consuming enough when you know your subject matter. Do not allow yourself to become a lazy programmer, or the sleepless nights that come weeks or months later will quickly give you a reason to be lazy.
  2. The second most important thing to remember is that the people who will be using your framework do not have anywhere near the knowledge of its internals that you do. As a result, you must:
    1. Keep it simple: Prefer strong typing to DataTables and generic collections. Prefer method overloads to lots of methods with slightly different names. Prefer multiple classes to gigantic classes. Introduce “convenience methods” into your classes (methods that perform simple conversions or call groups of other methods). Do not be afraid to introduce coupling between related classes, but make sure that you do it sparingly. If you find yourself constantly forgetting where certain methods are located or passing invalid values to other methods, chances are you need to rethink your architecture (after all, if you can’t use your own code with ease, I guarantee your customers will experience major frustration).
    2. Validate inputs: Many times, users will just hack their way through a project, using only auto-complete as their documentation. As a result, they may pass invalid values without knowing any better. Do your best to ensure that this won’t cause strange things to happen.
    3. Give descriptive error messages: There is nothing more frustrating that receiving a null reference exception from within a method and having no idea why it is failing.
    4. Assume complete ignorance: Every day, hundreds of ignorant CS students are in training at your local university. Every day, thousands of ignorant developers buy software components. Eventually, some of these guys will buy your products.
  3. The third most important thing to remember is that until your product ships, it is never too late to refactor public classes and interfaces. After your product is complete, take a good chunk of time to ensure that your framework’s naming conventions and processes are consistent and that everything makes sense. This is especially important for projects with large numbers of developers, but this simply practice can also immensely improve the architecture of one or two man projects. Keep in mind that once the product has shipped, even something as trivial as changing method names is generally out of the question. Taking 5 minutes to change that method name before the product ships will definitely pay off.
  4. The fourth most important thing to remember is: Test, Test, Test. Unit tests are a great start, but they are only a start. Quality frameworks have many attributes, such usability which cannot be measured by NUnit. As your framework nears completion, take some time out and use it. Not only will this help uncover design flaws and provide extra test coverage, but you should also have some solid examples of best practices to show your customers by the time you are ready to ship.
  5. The last thing to remember is: be consistent! Consistency comes on multiple levels:
    1. With “the” framework: It is extremely important that you are consistent with the frameworks on top of which your product is built (such as the .NET framework class libraries). The more consistent you are with those frameworks, the easier the transition to your framework will be to your users. This simple principle is one of the easiest to obey, but is violated time and time again by component vendors.
    2. With “your” framework: Equally important is that you are consistent within the walls of your own framework. Users will quickly become frustrated or confused if every time they open up a new namespace, everything functions differently.
    3. With “their” framework: If there are general design practices in your industry, do not ignore them. Chances are that they are there for a reason.

 

Posted by Jesse Ezell with 3 comment(s)

David Mendels (Macromedia) on Flex

David Mendels, who is with the Flex team posted some comments on Flex. I thought they were really good, so here they are:

Jesse, your final point is right where we are. We are not trying to position Flex as a head-to-head competitor or substitute good for XAML/Longhorn by any means. We think the design centers of the two products, target use cases, target users today are sufficiently differentiated that both can thrive. Both are very cool products.

At a high level, both technologies are trying to enable what Macromedia has been calling Rich Internet Application--apps that combine the responsiveness/interactivity of desktop apps with the ease of distribution of Web apps. But (simplifying) we are extending from Web apps up; and I see MSFT focused on desktop apps back. Further, our focus is the "reach web" where one can not ensure what platform (or what version of what platform) one's app will run on--Windows XP, 98, Longhorn--or Linux, Mac, PocketPC, Nokia. MSFT is driving to upgrade the worlds desktop Operating Systems and they are focused on Longhorn. That is valid, but it will take a long time and not meet everyone's needs.

Putting it in real world terms today at Macromedia: We are looking at building a new event management application for our web site. It has a public facing component (must be multi-browser/platform) and a behind the firewall component (should be cross-platform but we could restrict ourselves here) for administration. We want the rich data handling and UI that an RIA can provide. And we need it near term. We are building in Flex. However, one of our commercial product teams is looking at a new product that will not ship for several years--it is a desktop app (with a lot of internet connected functionality). It is a full, professional product, the needs to be extremely high performance (think Dreamweaver or Flash). We might use XAML in a case like this.

As for your points above that, about Flex being tethered to a server--that relates to the primary use cases we are designing for today--people who are building web presentation tier in JSP or ASP or CF but want the much richer data model and UI that is possible with a rich client app. However, for the long term, we are also looking at the disconnected case--it is just less of a focus for 1.0. So we are going to evolve the packaging, pricing and licensing models as we mature the technology for different use cases. Keep in mind that by the time Longhorn ships we will be on version 2 or 3 and will not just improve the product in a linear direction but broaden its focus in some ways as well.

You are also making some assumptions prematurely. We have not announced pricing or licensing options for ISVs. I can't do that now cause we aren't done -- but we are interested in feedback and what interest people have. This is a use case we think is important and valid, and ISVs embedding a version of the Royale engine that contains the pieces one needs at runtime is a configuration we need to plan for. We have some experience here--we already sell quite a bit of JRUN for ISVs who need an embedded J2EE server and provide an SDK that lets the ISV make the installation seamless and invisible to their customer. Of course, yes, we do charge money for software--that is our business--but the question will be for people to consider the value-add vs the cost rather than write off the option upfront.

Posted by Jesse Ezell with 3 comment(s)

Flex vs. Avalon

I've had Flex (Royal) on my machine for quite some time and was able to talk with the product team during the alphas. Now that Macromedia has publically announced a lot of details around MXML and Flex, I can finally say a few things that have been on my mind ever since my sneak peak of Royal.

A lot of people in the anti-MS camp will look at Flex and say, “hey, it's cross platform RIA solution, and XAML isn't”. Although it may be “platform independent“ to some degree, it suffers from a few of the same problems that the HTML model does as well as a few of its own.

First off, it is “server dependant.” Remember, you need to deploy the MXML file on the server in order to actually use it. When running offline, you are severly limited by the fact that you cannot call into a significant portion of your functionality, because it is all on the server. For example, lets say that you wanted to run an XML transform over some data and then output that as MXML or SVG and dynamically load that data into your interface. With Flex, this can be done ONLY when online, because all compilation takes place on the server. With Royal, such an operation is not going to kill you, because you have the full power of the platform when running in online and offline modes (there are a ton of other scenarios where the same limitation will come back to haunt you). Of course, this is why Macromedia calls Flex the “Presentation Tier“ solution, because it won't work for anything besides the presentation tier. The more client side logic your app contains, the less useful Flex will be.

Secondly, if you are an ISV, you should forget about creating Flex based applications any time soon. There is no way to deploy Flex apps apart from the server, so anyone who wants to run your app now has the additional cost / burden of the Flex server. Macromedia has not announced a free “Flex runtime” that you can distribute, so not only is your client base is going to be very small to begin with, but if you are not pricing your app at $50,000+ a pop, the server price may be a prohibitive factor when customers are looking into purchasing your app.

Thirdly, web service support in Flex is not nearly as good as what is already available in WSE. For one, security limitations in the Flash player will prevent you from making calls to any web services outside of your domain without using your server as a proxy server for the request (maybe not such a big deal right now, but that could mean a ton of extra traffic on your network if you have a lot of clients using your app...). Also, take a look at the list of Flex's supported standards and notice that the entire WS-* stack is missing (you get SOAP support, but that is about it... looks like Microsoft has Macromedia beat hands down on that front).

That said, Flex is definately a very cool product. However, if you think that it is going to eat into the market share of Avalon, you are dead wrong. Flex is for the next generation of browser based apps, Avalon is for the next generation of desktop apps.

[1] Macromedia Flex: the Presentation Tier Solution for Enterprise Rich Internet Applications. Nov 2003. http://www.macromedia.com/software/flex/whitepapers/pdf/flex_tech_wp.pdf

 

Posted by Jesse Ezell with 11 comment(s)

Mono Plans for Whidbey and Beyond

Miguel's write-up on the PDC is quite interesting. You can find it here. His conclusion (emphasis mine):

“Microsoft has taken another bold move in moving all of their new API development into .NET.

Not only are the new operating system features cool, but they have turned them into an API.

It is now our turn in the open source world to track these innovations, and expose turn applications into API providers.

It is important for Mono to continue its path (Note: we should do this in an orderly fashion, in peace if you will. Not screaming, waving our hands and banging our heads against the wall).

We have to leverage what is unique about Linux, iFolder, Gnome, Cairo, the VFS, our databases and expose those features to the managed world.

Mono needs to become a core feature of every application. “ [1]

[1] Lessons from the PDC. Miguel de Icaza. http://primates.ximian.com/~miguel/archive/2003/Nov-13.html

Posted by Jesse Ezell with no comments

Use Sql Server as Your Indexing Engine

I didn't realize this until today, but not only does SQL provide the great full text search capabilities everyone knows and loves, it can also index binary content (.doc, .xls), etc. without much extra work on your part.

To get this cool feature working, all you need to do is add a column to your database that has the file extension of the content stored in your data field (must be image type field), and then when you set up your index, just tell SQL server that this column is the file type column and you are set. Now, you can run standard fulltext queries on that column and it works like magic. Very cool.

Posted by Jesse Ezell with 1 comment(s)

Whidbey Design Flaws (Part 2)

Rob Howard writes responses to my criticism of the web Security namespace, noting that they had much of this discussion internally before deciding on the final outcome.

Still, I must take issue with him on a few points.

“> Why is GetNumberOfUsersOnline a method of the IMembershipProvider interface?
Because it's surfaced by the Membership provider - BTW, we're moving to abstract base classes in the beta (no more interface for any of the provider features) “ [1]

Then, why is it in MembershipProvider? Really... I don't see much value in this method, especially considering that it isn't even reliable anyway.

“With regard to AD we realized that AD doesn't support this, but we wanted to add AD support.” [1]

But, this isn't supported by AD, so it would take a modification of the AD schema to get it working, and even after that it wouldn't make sense to do this, because the web server would be the only place you could do this. It wouldn't work anywhere else, and since AD is usually used across the entire corp, not just some intranet app, it really doesn't make sense. I guess it makes a little more sense with ADAM as your user store, but most people aren't running ADAM currently (and then, you still have all the other LDAP based providers out there with the same issue).

“> why is there a GetPassword member
Ok, so what about the cases where the password is retrievable?” [1]

There isn't any rule that says an interface implementation cannot support more functionality than the interface it is implementing. As a general rule, however, passwords should not be retrievable. If someone wants to make their app insecure, make them do a little work (secure by default, right?).

“The obvious trade-offs here are complexitity vs. simplicity. I've personally maintained that the simpler and more understandable the software is the less bugs and support problems you will have and more people will use it because they can actually understand it! Furthermore, the pure object-oriented philosophy is somewhat elitist -- it places emphasis on who builds the software not on who uses the software, i.e. only the person who built it trully understands how it works due to the complexity. Our goal is to provide a model to address the problems of the majority - who will never extend our base functionality while still allowig the more advanced developers to extend our design, hence the 'provider design pattern'.“ [2]

I'm not advocating a million seperate interfaces being composed into one big object. However, there should at the very least be an interface that is common across all implementations. And by common, I mean an interface that is actually implemented across all valid implementations. If you can't depend on the contract, why have the interface in the first place? It is hard for me to understand how an interface that will randomly throw generic exceptions for methods it doesn't support (or return invalid values like the GetNumberOfUsersOnline method), makes the system any easier to use or accomplishes the goal you state. At least if there is a common interface, I know what features each implementation is going to provide and I can code against them. If you insist on violating such a simple principle, then you should at the very least provide for a way to query which parts of the contract that the interface supports within the contract and require a certain minimum subset of functionality. Then, I can do things like hide UI elements that line up to these properties/methods if I know they are going to fail if I call them, rather than putting up incorrect information on the screen or advertising features that aren't going to work anyway.

To me, it doesn't look like these are tradeoffs in terms of usability. They look far more like tradeoffs for features. I admit that it is cool to have support for secret questions and answers, number of users online, etc. all built-in. However, seeing that most implementations outside of the sql provider aren't going to support many of these members, it seems strange that the functionality of one provider dictates the architecture of the rest.

[1] http://weblogs.asp.net/jezell/posts/37052.aspx#FeedBack

[2] http://weblogs.asp.net/rhoward/posts/37112.aspx

Posted by Jesse Ezell with 3 comment(s)

Whidbey Goes To Far?

Why is it that Microsoft can't seem to call users “users” and groups “groups?” Role based security is great and all, but how many people outside of the framework team actually call groups “roles?” I guess User wasn't short enough either, because someone thought it had to be called a “MembershipUser” instead.

Why is GetNumberOfUsersOnline a method of the IMembershipProvider interface? After all there is no way to accurately determine this if you are using the SQL provider (yes, they do have a “workaround” for the obvious problem, but the number definately is not going to be accurate, and the IsUserOnline method can't be trusted to return valid answers either). However, if that wasn't enough, the fact that the AD implementation must always return 0 should have been another clue.

Is the person who came up with that bright idea the same one who decided that the interface should support secret questions and answers? Again, the AD provider doesn't support this either, but just throws a generic HttpException containing the text “API not supported”.

On the same note, why is there a GetPassword member, which also cannot be supported (and for a good reason) by most directory services (including AD).

How is a generic exception containing the text “API not supported“ any better than a “Method not found“ exception thrown by the framework? Why do we have interfaces in the first place if we aren't going to require that classes implement their contracts?

So, we have crappily named interfaces full of members that can never be implemented under many circumstances. Maybe they should have just made them an application block instead so that we could ignore them.

Posted by Jesse Ezell with 5 comment(s)

ProGamers

Korea is an interesting place... especially if you play StarCraft. It is unreal. These guys have like $60,000 a year (USD) salaries in Korea to play StarCraft on TV. It is like football out there (there are 50x as many StarCraft players in Korea as in the rest of the world combined).

Interview with ProGamer “Grrr...“:
http://www.war3.spb.ru/vods/GuillaumeInterview.zip

Recorded TV Match... take a look at the crowd... the stadium is filled:
http://www.war3.spb.ru/vods/olympus_final_xellos-vs-yellow-1.zip

Starcnomics:
http://www.blizzard.com/insider/017/overseasmerchandise.shtml

“Starcnomics is an academic look at the positive effects StarCraft has had on the Korean economy. A translation of the jacket summary reads:

"StarCraft Syndrome": It's more than an obsession with and devotion to the most popular game in Korea. It's the effect the game has had in generating new trends and socioeconomic changes. Economically, the syndrome created a new type of Korean industry or business that grew out of the needs of the times”

Posted by Jesse Ezell with no comments
More Posts Next page »