Eugene's profileI think, therefore I spa...PhotosBlogListsMore ![]() | Help |
I think, therefore I spam. |
|||||||||||||
|
April 29 Novell is hiringNovell PlateSpin team is hiring!
PlateSpin has been acquired by Novell and it is a great company to work for. Checkout the careers section: http://www.platespin.com/careersApril 23 Taking control of your application development - finding correct abstractionsAt this point I'm going to go ahead and claim that finding correct abstractions and coming up with interfaces is the most difficult thing in application design. Note that I'm talking about design, not implementation. Implementation might carry a load of technical difficulties and workarounds and digging through the web. But that's what they call "mechanical" problems. Often this is what is assumed programmers are meant to do, but I'd say that in mainstream software development most things have already been figured out, articles have been written and examples are available for download. That's the kind of work that said to take about 10% of overall development time. On the other hand, abstractions are always domain-specific and while writing them down or typing up or diagramming on the board is easy, it requires deep understanding of the problem domain and applicable use-cases. Usually the process involves more than one person. Depending on the scope it might require coordination of multiple designers/architects to ensure consistency throughout the system being produced. Leaving these difficulties aside, you have to come up with abstractions that are easy to use correctly, but more importantly are very hard to misuse. Comments in the code are a lie and the code itself is the ultimate documentation and first and foremost it should be written for other people to read and make use of. I'll admit I've done my share of mistakes, but I was fortunate enough to be able to start from clean slate and try something different (and hopefully better) every time. After having designed half a dozen decent-sized applications from ground up I came up with these observations: - Separation of concerns is easy to accomplish with layered architecture; - Role-based interfaces with very few verbs over relatively large number of nouns allows you to build Chain of Responsibility with ease (HTTP with its 4 verbs is the ultimate example this), cut down on the lines of code and are easy to understand at glance - w/o looking at the details of implementation; - Practicing ubiquitous language and keeping domain model rigid with Services, Entities and immutable Value Objects (Domain-Driven Design concept, not DTO) simplifies understanding, use and change; - Thinking about external dependencies (like persistence, communications with other systems, etc) in terms of services for the Business layer to consume establishes solid ground for defining interfaces with Data Source layer; - Having separate unit test projects for every layer gives you sense of accomplishment, confidence and freedom to change things; - Once all that is done, wiring it all together with Dependency Injection framework of your choosing becomes trivial; - Adding integration test project to ensure that various parts of the application talk to each other frees you from having to run UI to test a change.
Each one of those practices helps, but taken together they end up amplifying the effect of each other. Let me tell you, going through a month of intensive development following these practices feels like a vacation. It keeps the management happy too because there's always solid and verifiable progress and thanks to extensive testing the definition of "done" is really inclusive. I think I'll conclude on this happy note. April 21 Taking control of your application development - managing dependenciesIf we look at wikipedia article for coupling, we'll find that it's synonymous with dependency. Just about everybody know that coupling is bad and yet you can find a dependency graph like this:
Presentation->Business->Data Source
(meaning Presentation depends on Business that Depends on Data Source)
Assuming the implementation is not superficial and nothing like typeless datasets are being passed directly up to the Presentation, let's look at what this graph allows:
- direct use of Business abstractions in Presentation (good)
- no direct coupling of Presentation with Data Source (good)
- Data Source driving the interface/protocol for communications with Business (bad)
- testing of Data Source in isolation (worthless, because unless our Business abstractions are just DTOs we are not involving any Business rules)
And what it doesn't allow:
- testing Business in isolation (bad)
- testing Presentation in isolation from Data Source (bad)
- substitution of Data Source with another implementation (bad)
- and related to the previous, reuse of Business w/o the reuse of Data Source (bad)
Does that look like Pit of Success to you? I don't think so.
Here's another graph suggested by Domain-Driven folks like Eric Evans and Jimmy Nilsson:
Presentation->Business<-Data Source
This graph allows us to keep all the good stuff from the previous graph and eliminate all the bad stuff.
I want to elaborate a bit on the substitution of Data Source implementation. While this might seem unlikely, recent years have proven that Data Source and Presentation are the most likely targets of change (once the Business functionality has been achieved).
Imagine porting your ASP.NET application to Silverlight and you'll realize:
1) Silverlight means you're adding another application (client for you web-app server!). There are of course other likely clients that you might get. If you're like me you'll want to involve the Business rules as early as possible and that means... Business layer, hopefully reusing the implementation you've created for the server.
2) the change is not unlikely given the feasibility
3) the change is not feasible if you have to drag the Data Source implementation along.
It might seem at first that we have a circular dependency here, but that's not the case.
What are the Business abstractions that would allow as to do it? What is required from the infrastructure to let it happen?
Tune in later for the spectacular conclusion! April 16 Taking control of your application development - pit of successThis series of posts was long in coming and today seems like a good day to start it.
Over the last few years I've had a few conversations about structuring an application and found that while there’s a solid body of knowledge and proven practices available people don’t care much about it or misinterpret it. From what I’ve seen, coming up with the structure as you go or creating a superficial one leads to fast take off, but slow progress, the pace that gets slower all the time.
I’m not talking about heavy investment in infrastructure or design upfront. You will make adjustments, but having a good start is like digging a Pit of Success. Your developers can’t help, but fall into one.
In most abstract terms what it comes down to is planning the tiers and... here it comes... layers, if any, your application will have. The most obvious practical aspects are: - What processes you’ll run, - Where will they run, - What your dependency graph for each process should look like. Obviously all of it highly depends on the requirements; however the software industry in general through trial and error seems to have settled on certain ways of dealing with certain class of problems. Fowler calls those Patterns of Enterprise Application Architecture.
Here’s the default layered architecture according to Fowler:
He makes a distinction between layers and tiers here, because a lot of people confuse the two. Essentially, by Data Source we mean a bunch of our abstractions (classes, interfaces, etc) that talk to the database and other systems. It does not include the database itself. That’s another tier – one that might or may not happen to be running on the same machine, but we consider it separate.
The distinction is important because we’re defining the application boundaries. For example in a client-server application, what we really have is 2 applications with their own boundaries and the choices of layering should be made separately for the two.
There might be a sharp learning curve in learning the concepts, but all the tools to implement the infrastructure for common set of problems already exists and available in a number of flavours.
Traditionally tools drove the approach to the solution, but I believe the tools are just means to an end. Let’s start with “What do we want our solution to look like?” this time around. Read about the quality attributes I quote from Patterns of Software by Richard P Gabriel. I think everyone would like to see those quality attributes in their application. What can we do from the start?
Tune in later for the second part, where I’ll go over the language (abstractions) the layers might want to talk in and what my preferred dependency graph looks like. |
|
||||||||||||
|
|
|||||||||||||
|
|