[started writing this in Sep 2008; will post now, though not really a complete thought.]
What I dislike most about implementing a domain model with Hibernate (in Java) is how relationships are not treated as first class elements of the model implementation. Consider how with ER diagrams, the concept of a relationship holds the same importance as the entities.
The problem is that the developer must write all of the relationship maintenance code, which is especially cumbersome and error-pone for bidirectional relationships (short circuiting infinite mutual recursive calls; add and remove methods; etc.).
I'm wondering if there might be some way of using Scala traits to mix-in a bidir relationship to the two connected entity classses...
Tuesday, September 23, 2008
Monday, September 22, 2008
Domain-Driven Design
Started reading Domain Driven Design. Will try to write about my thoughts on the book and the subject as I proceed.
The key point thus far is that the domain very much represents a common language that will be used to communicate ideas, requirements, and behaviors (both of the system and the business) between developers and domain experts. At the same time it must be comprise a functional piece of a software system. This dual role will help keep the requirements of the users and the design of the software in sync. The model should not in any way be concealed from the domain experts (and users). It should be used as the language of communication. When either side finds it difficult to communicate aspects of the software or of the business using only the lexicon of the model, it is quite likely that the model is not "right", in that it either does not properly "map" to reality, is overly complicated or focused on technical (software) details, or is incomplete.
Accept that that the model will never be perfect, but must evolve continually evolve as everyone (developers and domain experts) works towards the development of the software. It is important to remember that even the domain experts, while knowing the business side very well, may not know how to formulate their understanding into a formal (and executable) model.
The model does not need to model everything known about the business, only what is pertinent to the current goals of the software system. It is a model of some reality, after all, and not a duplication of reality.
The key point thus far is that the domain very much represents a common language that will be used to communicate ideas, requirements, and behaviors (both of the system and the business) between developers and domain experts. At the same time it must be comprise a functional piece of a software system. This dual role will help keep the requirements of the users and the design of the software in sync. The model should not in any way be concealed from the domain experts (and users). It should be used as the language of communication. When either side finds it difficult to communicate aspects of the software or of the business using only the lexicon of the model, it is quite likely that the model is not "right", in that it either does not properly "map" to reality, is overly complicated or focused on technical (software) details, or is incomplete.
Accept that that the model will never be perfect, but must evolve continually evolve as everyone (developers and domain experts) works towards the development of the software. It is important to remember that even the domain experts, while knowing the business side very well, may not know how to formulate their understanding into a formal (and executable) model.
The model does not need to model everything known about the business, only what is pertinent to the current goals of the software system. It is a model of some reality, after all, and not a duplication of reality.
Over the years, I've hobbled together an application for personal finance management. Written in a combination of elisp (xemacs UI), perl (server), and shell scripts (command-line I/O), this was a fun exercise using "old school" development technologies. I believe I started it right around the turn of the millennium (2001?) to replace my use of M$ Money (allowing me to finally ditch use of Windoze altogether). Later, for a database class I was taking at UMass, I rewrote most the app, separating the database persistence and querying layers into a Perl-based server daemon with a proprietary I/O protocol. The xemacs-based UI is entirely text-based and keyboard-driven, of course, and has slowly grown to accommodate new functions. This app has served me incredibly well, providing an extremely efficient means of entering and querying my financial data. It even automatically balances my checking account for me, using downloaded account data and with strict and fuzzy matching of transactions to reconcile account statements. But the software is still missing a number of important pieces, including budgeting features, investment tracking, and UI support for many minor functions (I use manual SQL frequently). Adding these features to the existing system is entirely possible, but it would really just be busy work, without providing any real satisfaction of engineering accomplishment.
Having a few years under my belt using "modern" enterprise development technologies such as Hibernate, Spring Framework, and JavaServer Faces for my professional work, I've been itching to use these (and others) to re-engineer the app. I figure if I declare this in writing, I'm more likely to actually do it. Consider this posting as the official declaration.
I'd like to use this re-engineering effort to not only apply what I've learned from my professional work, but to push my skills and techniques further along and to try out new architectural ideas I have in mind. The re-engineering should also provide a good venue for trying out new technologies that would be too cumbersome or risky to test out on project at work. For example, I intend to take a look at Seam and SeamGen, possibly running under JBoss. I'd also like to assess the latest features of Spring 2.5. And I'd like to see what I can do to address the "bad smells" that have been wafting my way from the Hibernate domain model impementation in use on my work project. I'd like to even consider Scala features to see whether I can address some of the model implementation issues with new language constructs, such as Scala's traits. Hopefully, I'll write about some of my concerns and ideas as I move along with this project.
Initially, I intend to rewrite the server portion of the app using a SOA, and keep the xemacs UI. That should be an interesting mating of technologies from different eras, although I'll have to be careful if/when I flip the switch that connects these to layers, lest I cause some sort of technological anachronism with serious space-time implications.
Having a few years under my belt using "modern" enterprise development technologies such as Hibernate, Spring Framework, and JavaServer Faces for my professional work, I've been itching to use these (and others) to re-engineer the app. I figure if I declare this in writing, I'm more likely to actually do it. Consider this posting as the official declaration.
I'd like to use this re-engineering effort to not only apply what I've learned from my professional work, but to push my skills and techniques further along and to try out new architectural ideas I have in mind. The re-engineering should also provide a good venue for trying out new technologies that would be too cumbersome or risky to test out on project at work. For example, I intend to take a look at Seam and SeamGen, possibly running under JBoss. I'd also like to assess the latest features of Spring 2.5. And I'd like to see what I can do to address the "bad smells" that have been wafting my way from the Hibernate domain model impementation in use on my work project. I'd like to even consider Scala features to see whether I can address some of the model implementation issues with new language constructs, such as Scala's traits. Hopefully, I'll write about some of my concerns and ideas as I move along with this project.
Initially, I intend to rewrite the server portion of the app using a SOA, and keep the xemacs UI. That should be an interesting mating of technologies from different eras, although I'll have to be careful if/when I flip the switch that connects these to layers, lest I cause some sort of technological anachronism with serious space-time implications.
Sunday, July 20, 2008
Declarative Application Design
Some miscellaneous thoughts on designing applications to support declarative instantiations.
I find that as an application design matures, it evolves towards a declarative design, where the procedural/imperative code implements the mechanism/machinery of the application, and the declarative "code" implements the "policy", which is to say that it defines an instance of the application for a particular customer (business rules, UI look & fool, etc.). E.g., Data table columns are declared, rather than being specified in code; user interface is declared in *.xhtml files; etc.
It seems like all frameworks evolve from particular application instances, and that as developers seek to generalize their solutions, they create this separation between the mechanism and the policy implementations. At this point a framework emerges.
The need for a clear separation between the mechanism and the policy is certainly coming to the forefront as a concern on my current project, as the application is being adopted by other customers and will need to be configurable for each customers' particular needs.
A highly declarative application design would mostly get around the web application server restart problem, since the declarative portions are not Java, but text configuration files, which can be reloaded by the application. We already see this working with UI design, which is easily modified and redeployed with .xhtml files.
With a declarative design, I begin to think of unit tests as those which test the mechanism implementations, and the acceptance tests as those that test the policy.
I find that as an application design matures, it evolves towards a declarative design, where the procedural/imperative code implements the mechanism/machinery of the application, and the declarative "code" implements the "policy", which is to say that it defines an instance of the application for a particular customer (business rules, UI look & fool, etc.). E.g., Data table columns are declared, rather than being specified in code; user interface is declared in *.xhtml files; etc.
It seems like all frameworks evolve from particular application instances, and that as developers seek to generalize their solutions, they create this separation between the mechanism and the policy implementations. At this point a framework emerges.
The need for a clear separation between the mechanism and the policy is certainly coming to the forefront as a concern on my current project, as the application is being adopted by other customers and will need to be configurable for each customers' particular needs.
A highly declarative application design would mostly get around the web application server restart problem, since the declarative portions are not Java, but text configuration files, which can be reloaded by the application. We already see this working with UI design, which is easily modified and redeployed with .xhtml files.
With a declarative design, I begin to think of unit tests as those which test the mechanism implementations, and the acceptance tests as those that test the policy.
Tuesday, April 1, 2008
DSLs == Metalinguistic Abstraction?
From what little I've read so far, I have yet to see the novelty of the recent DSL (Domain Specific Language) trend in the software industry. Ever since reading the section on Metalinguistic Abstraction in Structure and Interpretation of Computer Programs, I've always tried to view the code I write as an exercise in language creation:
However, one aspect of DSLs appears to be concerned with the ability to use programming language features in ways that make a DSL look like something other than their host language. For example, via fancy operator overloading; the use of closures and function invocations that look like data; avoiding the use of optional, cluttering syntax like line-terminating semi-colons; etc. If creative use of syntax and host language features increases the expressiveness of a DSL, I'm all for it. But I feel this aspect of DSLs should be clearly separated from the idea of metalinguistic abstraction.
Update: Just saw that the Wikipedia entry for DSLs does in fact contain a reference to metalinguistic abstraction, so I feel validated on my above post, even if I'm behind the curve.
It is no exaggeration to regard this as the most fundamental idea in programming: "The evaluator, which determines the meaning of expressions in a programming language, is just another program." To appreciate this point is to change our images of ourselves as programmers. We come to see ourselves as designers of languages, rather than only users of languages designed by others. In fact, we can regard almost any program as the evaluator for some language.So the act of defining a set of methods, an API, or a framework is the act of defining a language in which to define a computational process. It seems to me this new fangled DSL idea is just a restatement of the concept of metalinguistic abstraction.
However, one aspect of DSLs appears to be concerned with the ability to use programming language features in ways that make a DSL look like something other than their host language. For example, via fancy operator overloading; the use of closures and function invocations that look like data; avoiding the use of optional, cluttering syntax like line-terminating semi-colons; etc. If creative use of syntax and host language features increases the expressiveness of a DSL, I'm all for it. But I feel this aspect of DSLs should be clearly separated from the idea of metalinguistic abstraction.
Update: Just saw that the Wikipedia entry for DSLs does in fact contain a reference to metalinguistic abstraction, so I feel validated on my above post, even if I'm behind the curve.
Subscribe to:
Posts (Atom)