|
In this episode, Michael and Markus talk about software components. We first looked at a couple of attempts at defining what a component is. We then provided our own definition that will be used in the rest of the episode. We then looked at the promises of component-based development: why are components useful? We then discussed some of the typical metadata components should specify to make them useful. We discussed to some extent typical variations in component models. The next topic was the separation of concerns between the component functionality and functionality provided by the component's execution environment (aka. container). We concluded the episode with the notion of architecture as language, where you use a formal DSL to describe a system's architecture. Components are the basic building block for this approach. TranscriptSo, hello Michael. Hi Markus. Well, I think this episode is going to be interesting, we're going to discuss software components and component architecture and I think we both have, well, at least about some aspects we have both very specific opinions. So I guess, this might be controversial at times. Let us start with the definition of what components are, what we understand by the term component. Markus, do you like to start? Yeah, why not. I mean generally component is a very much overloaded term and the most generic definition is basically a piece of software that is somehow separately usable or separately deployable. If you build a system, then you have for example a server component and a client component. This is very very generic and in my personal view not very useful. But people do use it that way, however that is not the way we want to discuss it, as you will see later. Another definition is, or another use and then if there is an explicit definition, is, you can find it in the graphical user interfaces world and if you listen to the Java podcast, you will probably know this discussion from the Nuxoll guy, what is his first name I forget, and he says basically if you have classes in an object or programmer language which also have properties as well as events to which you can register than that is what they call components and that is in the tradition of Visual Basic or Delphi, they all had those component libraries for visual components to interactively compose user interfaces. So I guess, then one of the key intentions is the reuse of software, so that is how it all started I believe in the sixties or seventies when the first discussions arose. It is this idea of being able as I said to separately use something and then of course to reuse something. So it should be somehow well defined subset of functionality that is, as the generative programming people like to say, that is minimally redundant and maximally composable, okay. So it should be composable with other components, the Lego® brick metaphor, you can assemble your system from stitching components together. And that is the reason why there is such an emphasis on interfaces, on defined interfaces that this component provides as well as those that it requires, right. So basically the context of a component: in which environment can this software component then run, what does it need? Absolutely. So that's one of the, in my view, really important concepts of a component. It should declaratively specify as much of its expected environment and of its provided services as possible. Why declaratively? How else would you do it? I mean you need some metadata that describes it all, you need very clear, very specific, very very clearly defined let us say idioms, coding idioms, so you can use some kind of reflection API or other tooling to inspect what a component does or depends on. Otherwise, you cannot build tools that build or compose applications by stitching together components because the tool cannot find out what a component does. It needs to be declarative for all, based on metadata is the same thing. So the metadata is the key point and this is maybe, I do not want to stretch it too much because then we get into the model-driven discussion already. But another important point is the deployability. You should be able to deploy the component in different environments, it should not … Well, it should not have any implicit assumptions of the environment. All the environment dependencies must be explicit. So, when you do deploy it in some environment, you can tell whether it is going to work or not. Ideally statically. That is at least how I see it. So, if you go back to other uses or definitions of component, the UML also has a notion of component. It is basically, if you remember the UML, it is basically this rectangle with these two small rectangles, I think on the left or right side, and they considered the small as a deployment artifact. So they have this deployment view of what a component is, it is in my personal opinion not very useful. Another thing that comes to my mind is the discussion about binary compatibility of the interfaces. How important is that? I remember that the IBM SOM discussion really focussed on this as well as Microsoft© COM technology did. Is this still relevant this discussion today? I personally do not see this as a defining property of a component. Well, it depends on how you compose your system, whether you want to be able to compose the system by composing binary components, right, then of course you have to be able to have this binary plugability and then you need the metadata somehow embedded in the binary distributable. But there is also a good use for components that are more relevant during the construction of software, when you work with the source code. In that case, there is no need for binary plugability, I would say. So, in my practical experience typically if you consider components as an architecture building block for building systems, then the binary plugability is not an issue, what so ever. Okay, and what did you want to say right now when I disrupted you? Oh, I only wanted to say that there is also this kind of classic definition by Clemens Szyperski, which I think you looked up. Yeah, this is one of the definitions I looked up and there is a one key property that he states that it should not have persistent state a component. And so, what is your opinion on that? Well again, we will discuss that later and much more detailed but I think what a component really is needs to be defined for a specific system. So there are systems where the architects decide that components are stateless, and in that case, components obviously should not have state and also no persistent state. But there are also other systems where the architect says well, there are either stateless or stateful components and there are components that might have persistent state or non-persistent state or there are components which themselves do not have state but they manage access to database which is also some kind of state. So, I think that the core is that it should be defined per project or per system in some kind of, well, as you say we should not get to the model-driven stuff too early, some kind of meta model, right, some kind of definition of what we consider a component is or should be in a project. And that can in some projects include state and then not include state in other projects. That is my understanding there. So, what we realize is that it is really hard to give a broad and general definition of the term software component. But the core is, I believe, that you can use it separately, reuse it separately and deploy it separately with only explicit dependencies. Absolutely. And that is why this episode does not try to define it, we want to discuss how they are used, what their properties can be, what the typical variability is. And then of course it is important that in a specific project you actually define for your project what you mean by a component. So, why are components useful? You mentioned it already partly, you, yeah, why are components useful, Markus? So of course, again this is my personal, somewhat personal view. There is this traditional view where you say components, you know, there is this component market place where people create components and then they are put in this global repository where people can then grab them and assemble their systems from it. I do not think this idea of component-based reuse has ever really materialized. I do not see that happening. And also it is kind of not fashionable today anymore because today we all do SOA, we reuse hosted services. So, I think components are useful for another reason. If we build systems with today's programming languages then those programming languages are not able to express architecture, okay. A programming language expresses, well, implementation code on a very fine-grained granularity, you have classes, you have procedures of methods, of functions or whatever, and you have the implementations of those. But you cannot easily say how your system is created or composed on an architectural level. So, if you compare components with Object Oriented programming, then I would say that what classes are for the implementation, for the program is what components are for the architecture. So, they are architecture's smallest relevant independent building block. So, if you build a system, then you decompose your system into components, those components have certain properties and responsibilities and it is up to the architect to define what those are and we will talk about that. And inside the components, you might have whatever other paradigm to actually implement them. So, components are the smallest architecturally relevant building block, foundation for architecture. And what kind of, do you have other abstraction levels beside components then, or is basically everything a component and you would have hierarchical components, or how do you orchestrate this? This is a very good question. First of all, it is important to say, and again we'll talk about that later, there is also another side to component, which is in most systems that I build or see or work with, a component is not able to exist on its own, it is somehow managed, ran or hosted by some kind of container or environment that provides additional services. We all know that from EJB or J2EE where you put an enterprise Java bean into a container and it provides transactions and scalability and all that stuff. You know all that, so that is kind of boring. So, in that sense you do not just have components, you also have a container that hosts them. And it is up to the platform architect to distinguish what functionality goes into the components and which of the functionality is handled by the environment, by the container. However, I think your question was getting somewhere else and I think what you kind of probably really asked was, assuming you already factored out this container, is everything else components. And there I would argue yes because, as I said before, in a project there can be, you have to define what a component is, there can be different kinds of components in a project, so you could argue that everything is components up to or I should say down to a certain level of granularity. Once you get inside components, then you implement them using whatever out of technology and then, of course, stuff is not a component anymore. You already mentioned hierarchical components; I think we maybe discuss that later when we talk about what components, which variability they can have. But that basically means that you compose a component with basically interconnected instances of other components and then you have a recursive structure and if you argue that way, then of course everything is a component. Would you agree or do you see differences? No, I mean what I learn is that the way you use the term component is, you define it in a specific context and this, in the last sentences you defined it in the architecture context how components can help you to structure and align and basically provide a foundation of your architecture so that you have, so that you are enabled to structure your functionality according to technical concepts, it allows you an easier mapping later to technology, this is what I feel. Exactly, that is also one of the core premises of the idea that a component description if you say, you know, it provides those services, it uses these other services and maybe some other metadata which we talk about later, it is technology independent on the specification level. And then you can implement that component using OO or a functional programming or whatever and then you can use automated tools if you want, of course you do not have to, to then map that component to certain, well, environment or container or technology and that gives you a degree of freedom between the component, its metadata and the implementation on one side and the technology choice that is governed by non-functional requirements, well, and hype I guess. Okay, before we are going to further details I like to have one discussion that I really needed to grasp and understand the concept of components, this is: Are components, do components require object orientation or what kind of implementation technology concepts, classes, whatever do I need to really provide and implement components? Do I have to use classes? Is a class already a component? This was pretty confusing for me as a beginner some years ago. In my view components and object orientation and classes are more or less unrelated. So lets elaborate a little bit on this. For example, you can have a component, which is intern, well, okay, so assume you define a component using all kinds of metadata and then the question is how do you implement it. One way to implement it is, you can take a class in an object oriented language and say this class represents let us say the façade, the external view of the component, it implements the interfaces the component provides and it has using some kinds of patterns and idioms and framework stuff, it has a way of describing and accessing the resources and all the other environment things that it needs to access. In that case you do use a class as an implementation artifact of a component harbor, inside that class of course you might have 15 other classes and 287 objects and 57 methods, so that is a granularity thing again. However, you can also say that a component, another kind of component is implemented by business rules, right? So you take a rule and, you know, some kind of rule specification language, whatever is the language of the day, I mean there are varied open source tools, you can also use Prolog or whatever and then the implementation is not object oriented at all. And you can implement it with this other technology. So, one of those, I think, key realizations is that if you build a system from components then there can be different components. Some components are, let us say, standard business logic components, they are implemented using OO. Others are rule components; they are implemented by a set of business rules. Others are process components, they are implemented by BPEL or BPMN or some other process description formulism. Other sources describe state-based behavior in which case they publish events they can work with and then internally there is a state machine that is triggered and then runs around. So, in that sense OO is one way of implementing components of, in other words, of providing the implementation code for the functionality the component wants to provide, okay. So, there is no direct relationship. That is what I was aiming at, right. So, maybe another confusion is how do you relate a component to a class versus to an object, like an object is an instantiated class, the class is only the plan for this object, for this kind of object. Now, what is a component in this context? Is it more a plan or is it more an instance? Yeah, this is one of my favorite topics because it creates confusion in almost every project I am involved in. So, here is my personal opinion. A component is like the class in the sense that it is instantiable. So, there is components and there is component instances, there is no other word for it in my view. And the component instances are instances of the component like objects are instances of classes, so they provide values for properties, they, you know, whatever instantiation means in practice. This also some-what depends on the definition of a component. However, there are systems where there is always only one instance of a component in which case it is kind of pointless to distinguish components and component instances. Let us look at an example. Let us look at an embedded system, and you want to describe a vehicle with components, a personal car, and you want a component that controls the window, right, the electric windows you can press a button and the component runs an engine, some electrical engine, that motor drives up the window or down. Then you have a component which you would call window controller, okay. And it for example knows how to talk to the electrical motor that controls the window and maybe it has an input that is fed from some kind of switch that is triggered by the window if it reaches the top position. So now, a car has four windows, so it is kind of obvious what you do. You define your window thing, the component, and then you have four instances of that, one for front left, front right, back left and back right, okay. So, in that case it is kind of obvious. Also if you have hierarchical components, then it is, well it is probably not obvious because that is where the discussions are all the time, but I think it is, if you think about it, it is obvious that if you compose a component from other component-like things inside, then these are component instances. Because if you look at the car as a whole in our example, you could describe the car's software itself as a component, which is then kind of instantiated for each car we actually build, and then of course each of the things inside the component are of course themselves instances. It is also like an object orientation. If you define a class, then the class does not contain other classes. It contains objects, right, variables, which are basically objects and the behavior and the functionality and the implementation of a class is composed by stitching together objects, not classes. I mean, yes, there are inner classes in languages like Java, but let us forget that for a moment. The classical object under the programming defines new types by connecting instantiated other types and writing algorithms around it, and it is the same thing in components. A component is something that can be instantiated and then connected with other components. So, now that we had some of the basics why don't we get into more details and so, what is really necessary, what should a component specify, what to the metadata contained and specified for the component? Yeah, let me step back like a half step, and that is, assume we have defined what a component is, how do we describe a system that is made from components? And I think it is obvious from the discussion we had before about the instantiation stuff that a component-based system is basically a system that is made up of connected instances of components. So, if you define a system, what you do is you take your bunch of components you have in your library, you instantiate them and then you connect them and the connection thing is what I want to get at. A connection is basically if some component says I provide this service and the other component says I require that service, then you should establish a connection, a wire or a connector between instances of those components so that the one instance of that one component knows which of those other instances actually does provide this specific service it requires at runtime. So, that is important, so, if you describe a system you have typically several view points, one view point describes the components, we just discussed that, with whatever properties they have, see in five minutes, another view point describes the composition which is instances of those components and how they are interconnected, and then a third view point typically describes the deployment or the system view where you say I want this component to run on some kind of server machine, another component on some other client machine, well, I should have said component instances, sorry, and then you also map them to certain execution infrastructures like whatever J2EE or EJB, whatever. So, these are there kind of three main viewpoints and that kind of leads into the discussion of what metadata it needs. If you want to describe a system the metadata needs to describe the components, it needs to describe the instances and their connections and it needs to describe the allocation of the instances to execution containers and hardware. That was kind of the system view. I think your question was targeted towards what a component as a type specification should include in its specification. Yeah, so maybe we could differentiate between the absolute minimum, the core, and some typical or nice to have or common properties that components in today's technologies typically specify and require. Yeah, so the minimum is the interfaces or services that provides and those it requires. So that allows you simple dependency checking so you know a system is only able to work with if all required services of all the instances you have are basically satisfied by provided services from other instances. One way of deciding what of this is minimal or not is simply to look at existing technologies. And if you look at typical today's dependency injection frameworks like Spring as the most prominent one in the Java world, and I guess http://www.spring.net, then that is exactly what they do. You describe the services you provide by having a class that simply implements certain interfaces and you describe the services you require by using certain dependency injection conventions either with sador methods or constructed parameters. So to recap, I think the minimum is to describe which interfaces you require and which interfaces you provide. Since we talk about interfaces, well, if you listen to us discussing here, this probably sounds to you a little bit like the typical RPC kind of thing, right, like CORBA objects or something. So, an interface is a collection of methods you can call synchronously, blocking and so on. And it is important to address that that is not the case. An interface is simply as a way of specifying how to interact with the component. And such an interaction can either be synchronous message call, sorry, synchronous procedure call based, in which case you have the typical interfaces as you know them from Java or CORBA or whatever OO-language. But you can also have a message-driven system in which case a component defines a bunch of messages it can understand and other messages it kind of sends out, it publishes as it is interface. So, in that case an interface is a bunch of messages and maybe a specification of how these messages relate, this is typically known as interaction paradigms, message interaction paradigms. So you say things like this is a request response paradigm where you accept the request message and then reply by one response message. Or there is another paradigm, the public subscribe, where somebody sends you a subscription message and then you send periodic updates of whatever thing you want to tell these other clients periodically. So, this is a different message interaction paradigm. So, an interface has to specify those. And this is exactly something that the architect would typically define at the beginning of a project, what kind of interaction the component should have, and I guess it also depends on the technology but very much on the famous non-functional requirements of the project whether it is highly asynchronous or whether synchronous invocations are sufficient. Absolutely. And it is not so much necessarily technology dependent because you can simulate like RPC-styled stuff through message or middleware and also you can have asynchronous and more decoupled things using things like CORBA. So it is more really as you said, it is this, an architect understands the requirements, understands non-functional requirements and then people discuss and discuss and decide okay, our system should be primarily message oriented in which case you will define components who's interfaces are, as I said, those message interaction schemes. So, is that the minimum or is this already some extended set of property? The definition of interfaces is minimum, well, how else do you specify something that it does or depends on. If you look at the message-oriented world, then I would say formerly defining interaction paradigms with protocol state machines or something, that is beyond the minimum. Okay, what else, anything else for the minimum specification? No, I do not think so. I mean, for the minimum … … it is the interfaces the provided and required ones and everything else is then depending on the context, on the project. The interfaces are independent of components, right, so you do not say a component owns some kind of interface, because that would mean nobody else could use this interface and that is kind of pointless. So, components, sorry, interfaces are contract specifications, they live on their own and components can then say I provide this interface and others say I require this interface. Let us look a little bit at how you can give more semantic meaning somehow to components. You said before, you asked the question, is everything a component. And I said kind of yes. And assume a typical enterprise system, you have stuff that happens on the client, that has a visual representation. Other stuff happens on the server and typically provides database access. Other stuff also happens on the server and does some business-logic computations or calculations or algorithmic stuff. So the question is, can you distinguish those and how do you manage dependencies because typically what you say is yes, it is possible that a GUI component can access a remote business-logic component, it is also allowed that a business-logic component accesses a database management data something component, but not the other way round. This is the typical layering stuff between all. We all know that layering is a very good thing for big systems. And one way you can easily merge that with the idea of components is that you associate each component or each component type with layer, you say you do have three kinds of components, GUI components, business-logic components and database access components and then you define what the allowed dependencies are, like GUI can depend on business logic, business logic can depend on database but nothing else, and then you can easily check when you specify or build the concrete system, you can use some kind of constraint checker that says hey, you have just violated your own rules, which is that the dependencies can only go in this direction. And another property that comes to mind is versioning. I mean, we discussed in the beginning that reuses are important and now you start off with your project, use a component of first time now every system evolves typically and what is inversion, too. How can you properly differentiate between the new generation, the new version of a component, how can you make sure that your system really uses consistently the new component version? Little technologies have in my mind and my understanding versioning support build-ins. I know that .Net has some versioning support and IBM SOM in the past did have, but CORBA did not really provide good versioning support, usable versioning support. And the problem with versioning is of course compatibility, right. If you want to make sure that if you have a new version of a component that the environment of that component can still use the new version without kind of crashing. So, you can want a pluggable compatibility, Plug-And-Play, right, you want to replace an existing version of a component with a new version and the system should still work. You want to have seamless upgrades if possible; I mean that is something that users are just so used today. Well, I do not download every new component of this new piece of software provider consistent subset that then installed and deployed will work together and not fail because of missing interfaces or a stuff like that. So, let us think about first of all what it means to be compatible. It means that a new version of a component provides all the services of the old component and maybe more and that it does not depend on additional environment, right. So, because the system might not provide that environment, you cannot plug it in. So, that is one of the constraints. And if you look at it a little big more semantically and think about pre- and postconditions which is by the way also something you can associate with interfaces and components if you want then this means that the precondition of some operation or interaction must be the same one as in the old version or others because it can handle the old stuff and more stuff and the postcondition is either the postcondition from the old one or a more specific postcondition. So, you "OR" the preconditions together and you "AND" the postconditions together. So, that is more the semantic view. But the key to making versioning possible is primarily metadata, right. So what you want to do is, you want to say that this component here is a new version of that other component. And then if you have sufficient metadata, you can again run a constraint checker that verifies that this new component actually does provide all the services of the old one plus optional new services and that it does not have additional environment dependencies. So, it is all about metadata. Once you have the metadata, you can run the checks and then you can statically verify that if you replace this component with its new version it will work. That there are no syntactical conflicts, the semantical are always a bit harder and here you need conventions or rules or stuff to fill that into the metadata to represent that somehow. All the pre- and postcondition stuff, right. If you define the pre- and postconditions with an interface and not with a component, then if you have a new version of a component implement the same interface, the same pre- and postconditions apply. So, it cannot violate the semantics. Now we all know that describing semantics with pre- and postconditions is not necessarily trivial and that you cannot describe all semantics, but that is typically also not needed in every project. But if there are certain aspects of the component's semantic that are critical to be compatible in subsequent versions, well, then come up with metadata for it. It is not possible to define all kinds of semantics with metadata in general. But for certain kinds of semantics that is important for your system you can come up with metadata or formal notations to describe them, it is not rocket science. Well, I have done it, so, it is possible. There is other stuff. For example, something that is kind of obvious is configuration parameters. If you look at executables in an operating system, then they have command line parameters. So, the same with components. A component can have a bunch of configuration parameters, which it reads at runtime to adept its behavior dynamically somehow. And typically, what happens is that the component defines the parameters and the component instance once it is instantiated or deployed provides the values for those. Kind of obvious but it is very important. Another one is ports. That kind of not that trivial, but consider the following thing. Consider a component that, it is a kind of stupid example I always have, is a component which transfers data from one database to another. So, it needs to connect to two databases. And assume the database thing is also a component. Then it would have basically a required service, a required interface, it would say I need the database interface in order to do something. However, it does not need one of those, it needs two of them. Because one is the source database and the other one is the target database. So, it is often not enough to say that a component provides a certain service or uses a certain service; it needs to be able to distinguish different roles of using that service, kind of communication endpoints. And that is what you do with the port. A port is simply a named communication endpoint of a component, which is associated with an interface. And then you can have several ports with the same interface and they can be connected separately with other instances. Another thing that goes more into the interaction with container or some hosting environment is some of the internal behavior. Is a component single-threaded or is it thread-safe? Does it have a life cycle; does it need to be activated? Can it be shut down by the environment, can it be passivated? What do you do if you restart? Can it be killed, does it have state, is it stateless, stateful? All these things might need to be specified depending of course on your concrete component definition, that is the whole point of this discussion. You might have to specify these things, so the environment can work with that sensibly. Another thing is how you want to wire the component instances. Are you able to say statically when you define the system that component instance A talks to some other component instance B or should this be resolved at runtime like I do have component instance A and it needs to talk to somebody who provides this and that interface and you can resolve that dynamically at runtime. That is what naming services and trader services in CORBA and other environments do. So, incorporating or distinguishing between static wiring and dynamic wiring is an important thing. The last thing I want to mention here in this discussion is, well it is the but last thing, is something how replicated state. When I was at a customer recently, they were building, well, they thought they were building a system that was basically based on message passing. So, they had components and interfaces and the interfaces were, consisted of messages that went into components or out of components, the thing we discussed before. However, after discussing a while we noticed, well, it is not really that they use message passing, what they really have is shared replicated state, right. So, there is some state in the system, which is provided by a certain component, which is updated by a certain component, and then there are other components, which read that state. So, the intention of what you want to really do is you want to define that state, you want to define who updates it and how often it is updated and you want to know who reads this state and how often it is read. So, my customer people were so much in this message oriented world that they were kind of trying to express replicated state with messages and of course you have to specify all kinds of things you need, messages that update a state incrementally or do complete refresh and all that stuff. If they change their perception from message orientated to replicated state then it is much easier, we just define a data structure and you say who publishes it and who needs it and how often you want to be updated. So, we changed the meta model that described the component, we changed what we mean by component to include a way of specifying that it creates and/or uses certain shared state. And that made the specification of the system, well, it reduced the size of the specification significantly because you did not have to deal with this low level message exchange stuff. The abstraction was not shared state. So, what I want to say is, certain component architectures might also have the notion of shared state as part of their definition what a component is. Okay. That was long. So, what other topic should we discuss? For example, the environment that you mentioned before, what kind of services does a typical component environment, also called application server very often … Yeah, or container … … What does it provide? Again of course, it depends on the domain in which you are working. A typical service is resource management, access to all kind of resources like threads, network connections, files, whatever. And as it happens, there is a book that talks about resource management; I think you know it well … Yes, I know it well by a coincidence. So, obviously Michael is the co-author of this book and it is about resource management and how to efficiently manage resources, and that is something the environment often does. You want to elaborate on that a little bit? Yeah, it is about all the strategies that you need for efficient resource management. As Markus already started, a resource can be anything in that context, it is a thread, a piece of memory or even processing time that you want to efficiently use and share potentially. And so in this book there is a set of patterns that describe how to interact with resources if you have a certain focus on individual non-functional requirements like if you focus on real time properties, you will choose the different set of patterns that avoid for example on demand loading and load everything up front, or if you focus on scalability, you will pay the penalty of not being so fast and so efficient but you will be able to scale your system to a much higher number of users, servers or whatever your scalability factor is. Of course, we had an episode back in the day in the se-radio podcast and will link to it. So well, that is one big thing. In general, it is the job of the container to manage the resources, the life cycle of the component instances and, well, the access of the component instances to those resources. And again, as you said these are different depending on the domain and what you really want to do, examples include the stuff you already mentioned, things like virtualization, so, making sure that the component looks as if it is still available by the new reality, it is kind of paged out and reactivated on demand, naming identification is another thing that components get unique identifiers and you can address them if they have state, remote access to components, this is the application server thing. There is by the way another book, which we talked about in a previous episode. Transaction management, error handling, logging, so, these are all the things that an application server or component container typically does. What you could say is that components handle the functional requirements, containers handle the non-functional requirements and the metadata that describes the component makes sure that the container knows what to do with the component. A topic that we did not hit on so far, but it is really exciting and sometimes causes long discussions and projects, is the differentiation between a component and a service like in service orientation today, like some claimed well, we do not do component oriented software development or component based software development, we do now service oriented software development. Now, it is your round Markus. First of all, in order to distinguish the two, we would have to be able to define both of them concisely, which we already noticed we kind of failed for components and as everybody knows it is impossible for SOA. So, that is the first problem. So, I think there is one thing that is kind of important and that is that in component oriented development you typically talk about, and that does not have to be like that but that is traditionally how it is viewed. If you want to reuse something, what you do is you grab that component and integrate it into your system basically by running it on your application server/container. In SOA it is a bit different. What you do is you basically say there is these services running all over the world or all over the enterprise and if you want to use it, you just remotely connect to it. But of course, I mean, I do not know, this is kind of not a hard distinction. Personally, I think SOA is primarily a bunch of hype if you look at least at the technological stuff. In many ways you can argue that Service Oriented Architecture is components done right or it is basically the same thing or it is a buzzword for it. I have a really hard time distinguishing the two. One thing is that in SOA you have the explicit distinction between like services and then business processes that work on those services. But I mean in a well-defined component based system you might have components, which encapsulate process and other components that encapsulate more basic services and then one causes the other. So, in that sense it is the same thing. I honestly have a very hard time distinguishing the two and I personally think the component-oriented view with the metadata stuff we discussed about is more grounded in a reality than some of the SOA hype. There is one thing I want to talk about briefly and that is service oriented architecture primarily looks at how a system provides a certain service. For example, if you look at the WSDL description of web services, which is obviously one way of building SOAs, not the only one, then a WSDL 1.X specification only defines the services somebody provides. It does not define what somebody depends on and that is because what you do define is actually a service and a service is really just something somebody else can use. You do not define a component, which is something that provides the service and uses other services. So, I think the best distinction I could come up with is that components can be seen as an implementation technology for SOA. A service is basically a bunch of things that others can use, that you provide and a component is actually the entity that uses a service or provides a service. Something that pops into my mind is SCA, the service component architecture, which is basically what you just said, makes it more explicit and actually provides a programming model that exactly represents this view. Right, so this leads us into the technologies, into the example technologies. SCA, the service component architecture, is, I think, a very very good component architecture and it is of course labelled under SOA because that is today's hype du jour. But I think the idea there is of course that you define component types, you can instantiate them, you can connect them, components can be structured hierarchically. They do use some other terms for some of those things, they have modules and stuff. But it is basically a hierarchically structured component model with then of course the ability to express or expose services in ways that are accessible to SOA systems like typically WSDL or some of these other things. So, it is a rather new standard, I forget what the institution is that defines it, they have created a new institution for it, I forget what it is called. It is certainly something to look at. When I saw it first, I was actually really happy because I saw many of my own preachings in it, because it was the first component, well, at least more or less recent component standard that looked at hierarchical deconstruction and some of these things and distinguished between deployment and logical instantiation and composition for those types. So, I think thy have done a lot of things right. Okay, so what other technologies, we had previous to this recording a discussion and there I asked you what technology provides the bare minimum of a component model. And you answered Spring. So, why that? Right, and it is not just Spring, it is basically all dependency injection containers because as we elaborated before, we said that the minimum that you need to do as a component is to specify what you provide, which interfaces or services, and what you expect from the environment. And that is exactly what the Spring core does. It provides a dependency injection framework. The container is basically, does not do anything else. So, it is kind of somewhat of a stretch to call Spring a container. But it does manage dependencies in both ways and that is a good thing. It also does provide certain non-functional support, support for non-functional requirements using Spring core's aspect orientation mechanism, so you can basically deploy interceptors around component instances that then for example provide remote access to component's interfaces or do some transaction stuff. So, in that sense I would say Spring core with its dependency injection is the absolute minimum, using its AO-features, you can even add non-functional requirement support or, well, support for container handled non-functional stuff using Spring. I would say that is kind of the minimum. So, if you rate Spring and Spring-like containers as the minimum, how would you rate EJB, COM and CORBA as some of the basically old guys today? Well, let us look at each of them separately. EJB as we all know is a direct competitor to Spring, the more current EJB releases, EJB3 specifically, is, well the Spring guys say, it is not up to what Spring can do, of course EJB's guys say the opposite. But I think it is obvious that EJB, independent of the version, was one of the primary first and widely deployed component infrastructures at least in the enterprise world where you really had an explicit container and you had metadata description, they call it deployment descriptors, and you had, your components were implementation of pure business logic, yes, you had all those life cycle interfaces and all that crap you had to write, it was early, people made mistakes, Spring improved on that. But I think the general idea is there and it did work well. COM is somewhat of a, well COM is not COM, there are many aspects, there is COM, there is DCOM, there is COMP+ and basically it is a relative early component model, had binary compatibility or plugability and, I do not know, it is very complex. It is, the specifications with all those GUIs and all that crap is not very nice, it is hard to use, it is tough to use. Don Box, kind of one of the gurus who used this stuff and who wrote about the stuff, once called it too complex. So, it was an old model, it was basically the direct competitor to CORBA, DCOM in case of remote communication. CORBA is not really a component model. CORBA is first and for most a remote communication's infrastructure. And the CORBA component model added a container to it where you could predefine certain life cycle. Well, the container came with certain predefined life cycle schemes like, I do not know, entity components which had state and stateless services, which had no state, and then you could basically add metadata to your CORBA objects and then the container would handle them according to that metadata. So, CORBA components is not used very widely, it is used in the defense world quite a bit but not that much. EJB certainly is on its, well I am not sure, I would not say it is on its way out. But it is not the only kid on the block anymore; the core Spring really takes away quite a bit of its market share. So, the technologies we talked about in the last couple of minutes are the traditional ones, some are historic, some are traditional, some are still current. But it is important to point out that many of them still are somewhat minimal. For example, in most of them, there is no out-of-the-box way to describe certain different component types; many do not support the notion of ports we mentioned before. The support for describing different metadata with regards to threading and active versus passive stuff is very limited. Many cannot have events, in some you cannot distinguish between static and dynamic wiring. Replicated state is something they all do not have. I am a big fan of actually defining a mount component model for a given project because none of those existing standards, I think, does what I need and more specifically I cannot easily extend it, and that is more important. So let us briefly look at some maybe lesser-known component oriented technologies. One is the Windows communication foundation's technology, formerly known as Indigo. It is basically a message oriented system but they also have components, which define the interfaces as a set of messages they consume and provide, and then you can basically define message cues which handle certain different properties, you can have transactional cues, and I think they call these things endpoints. So, that is actually very interesting and really modern and actually nicely done component infrastructure, I think. Another one is AUTOSAR, the automotive system architecture standard, it is basically a component-based middleware for automotive embedded software. In case you do not know that a typical personal vehicle these days contains 50-100 computers, which are connected with varied bus systems, CAN bus, MOST bus and other bus systems. And of course you need to have software in the car that works efficiently and that is distributed and then you have all kinds of variance of cars and special equipment and you have to dynamically, well, not dynamically but flexibly compose the overall system from components and the AUTOSAR thing is a standard there. Relatively new, I think 2003 was when it came out, and the interesting thing about it is that it is actually an embedded system. So, the stuff we talked about is not limited to big iron enterprise stuff, you can use it in the embedded world, of course you have to implement things differently, you do not have this big application server, you maybe have a modular embedded operating system, which you then configure so it can handle the kinds of components you want to deploy in it. Another thing that I heard recently about is Android, the Google mobile operating system that is currently hyped quite a bit, and without going into too much detail, we will put a link to a Google developer podcast episode into the show notes. It is also component-oriented. They again invented certain terminology, they talk about intents and intent receivers and that other stuff, I do not remember all of it. But it is certainly component oriented and has many of the characteristics we talked about before. The last thing I want to mention is Singularity. That is actually really cool. In case some of the discussions above sounded a little bit like, well, it sounds like components are programs and application service and container are basically operating systems. Yes, there is a relation there. So, Microsoft has a research project called Singularity where they have built a completely new operating system using this metaphor of components and metadata and verifiable metadata and static security and code analysis and all that stuff extremely cool and as it happens, the next episode of se-radio will feature an interview with the primary researcher who leads the project at Microsoft, Galen Hunt, and we will talk there about how Singularity kind of implements this notion of components. It is one of the reasons why we are having this component episode now in se-radio because this is a good foundation for the singularity episode next week. Okay, anything that we miss? Well, we have these esoteric questions, which we maybe, there is one thing that we did not talk about yet and that is: Are component models a domain model for programming? And I think this is really a very nice analogy. If you look at today's hype around domain-driven development and domain-specific languages and some of that stuff where people say you should understand your domain and then build languages around your domain, so you can efficiently express algorithm structures and simply stuff in that domain, then if you consider software architecture the domain, which is what you should do if you are a software architect, then the stuff we talked about, the component stuff is basically a way of defining a domain specific language for describing your architecture. And by doing that, by defining the language you understand, you formally define what a component is and what properties it has and how it works and how you specify it. And if you then use that language to define a specific system you have, well, this is basically a sentence in the language you define, the architecture of a specific system as a posted language, which specifies the abstractions you use for building systems. So, kind of a buzzword that I like to establish here is like architecture as language that instead of trying to write documents that describe an architecture, what you maybe should do is get together with your stakeholders and as you try to understand the architecture, really define a language, define a grammar using the suitable tooling that allows you to describe instances of that architecture, certain systems based on that architecture. And by trying to define that language what you do is, you refine your understanding of the architecture and formalize what the capabilities of the building blocks, i.e. components are. And I have used this in a number of projects and it is amazing how well this works. Because it allows you to express systems independent of technology and it removes all kinds of misunderstandings because if people say, you know, what is a component, you can point them to the grammar and say you know a component is something as you can see that provides a bunch of interfaces, that requires another set of interfaces, that is single-threaded or multi-threaded, you can specify that, it can, I do not know, produce events and it has configuration parameters. So, formalizing your architecture into a language is a very very powerful concept and components and their metadata descriptions are really really a good starting point. And I hope that this episode gave you a bunch of ideas about what a component can have in its metadata and its functionality. We also have a bunch of slides that we will put into the show notes. Okay, I think this was a perfect end for this episode. Thank you Markus. Thank you, bye-bye. Links
|