www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Component based programming in D

reply Bart <Bart gmail.com> writes:
I'm new to component based programming. I've read it is an 
alternative to oop for speed. I don't understand how it is 
possible to have an alternative to oop and still have oop like 
behavior(polymorphism) nor how to do this. It seems all the great 
things oop offers(all the design patterns) would be impossible. 
The benefits are suppose to better reusability as components are 
more isolated in their dependencies.

Can someone help me understand this a little better and how I'd 
go about using it in D? Specifically I'm looking at the pros and 
cons, what are the real similarities and differences to oop, and 
how one implements them in D(taking in to account D's 
capabilities).

Thanks.
Jun 18 2019
next sibling parent Yatheendra <3df4 gmail.ru> writes:
I guess design patterns are independent of implementation 
language. Anyway, I suspect OO is incidental in components. D 
probably can do it better than C++ at least. Do search for the 
video of a talk Walter Bright gave on component programming in D.
Jun 18 2019
prev sibling next sibling parent Marco de Wild <mdwild sogyo.nl> writes:
On Tuesday, 18 June 2019 at 09:17:09 UTC, Bart wrote:
 I'm new to component based programming. I've read it is an 
 alternative to oop for speed. I don't understand how it is 
 possible to have an alternative to oop and still have oop like 
 behavior(polymorphism) nor how to do this. It seems all the 
 great things oop offers(all the design patterns) would be 
 impossible. The benefits are suppose to better reusability as 
 components are more isolated in their dependencies.

 Can someone help me understand this a little better and how I'd 
 go about using it in D? Specifically I'm looking at the pros 
 and cons, what are the real similarities and differences to 
 oop, and how one implements them in D(taking in to account D's 
 capabilities).

 Thanks.
I don't know a lot about component-based programming per se. (I might use it all the time, I just don't know the term.) inheritance to compose behaviour, also known as polymorphism. This has a slight overhead at runtime. In like >90% of the cases however, you can deduce statically what override/implementation of a function will be called. In D, we have the means to make that deduction at compile time. The most simple means is duck typing: int fun(T)(T instance) { return instance.number(); } We have a templated function, that is: a function that takes an instance of any type. Think of generics, but more liberal. If we call the function with an object: class Dice { final int number() { return 6; } } fun(new Dice()); the compiler generates a template instance, that is, a `fun` that takes a `Dice` instance as its argument. It will then compile as if you have written the Dice type there yourself: int fun(Dice instance) { return instance.number(); } This compiles because the class Dice defines a method called `number`. However, we can put any type in there that defines a number() method. In classic OOP, one would use an interface for this interface Number { int number(); } class Dice : Number { int number() { return 6; } } Using duck typing, the compiler just checks whether the code compiles given the type. If we have other types that implement number, like a Roulette class, we can simply pass an instance of that class to the function and the compiler figures it out. We don't need to define an interface. For large methods, it can be quite unclear what methods a type need to define in order to be passed in. int fun(T)(T instance) // Only if T has number() method { // Large amount of code here return instance.number(); } In this example we can only pass in a T if it defines a `number()` method. We annotated it in a comment. However, D can also explicitly check it using traits (https://dlang.org/phobos/std_traits.html) or the nuclear option: __traits(compiles, ...), which checks if a certain expression compiles successfully. Doing it the quick and dirty way, we can explicitly define our desired instance interface: int fun(T)(T instance) if(__traits(compiles, {int x = instance.number()} )) { // Large amount of code here return instance.number(); } We add a constraint to our template: our function is valid for any T for which the number() method returns an integer. This is just the surface, you can read https://github.com/PhilippeSigaud/D-templates-tutorial for a technical introduction. One thing I really like about this is that we preserve the actual type during the whole function. This means that we can call other functions using a strongly-typed argument or do other things based on what type we get. In my personal project, I need to rewrite a bunch of functions that took one type (Card), but now need to take another, reduced type (SimpleCard) as well. The functions currently output cards grouped in sets. Card has some properties (e.g. isFolded, isShown), and SimpleCard is just the value representation (e.g. spades-4). I can use classic inheritance Card extends SimpleCard, but that means I lose my type info along the way. Using duck typing, my functions work for any Card-like object and preserve the type as well. If I need polymorphism, I can achieve that using normal overload rules, e.g. void fun(CardLike)(CardLike card) { foo(card); } void foo(Card card) {} void foo(SimpleCard card) {} void foo(FakedCard card) {} The classes can be kept small - new behaviour can be glued to classes without having impact on existing code. (I once though about why my pet project was progressing so much faster than regular projects. I figured because I rarely changed code - I just added code in different files and changed one line to activate it.)
Jun 18 2019
prev sibling next sibling parent reply =?UTF-8?B?QXVyw6lsaWVu?= Plazzotta <here gmail.com> writes:
On Tuesday, 18 June 2019 at 09:17:09 UTC, Bart wrote:

 Can someone help me understand this a little better and how I'd 
 go about using it in D? Specifically I'm looking at the pros 
 and cons, what are the real similarities and differences to 
 oop, and how one implements them in D(taking in to account D's 
 capabilities).

 Thanks.
Perhaps, you should be interested by this article written by our famous Walter: http://www.drdobbs.com/architecture-and-design/component-programming-in-d/240008321 You'll get a whole new idea about reusability :)
Jun 18 2019
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jun 18, 2019 at 09:22:28PM +0000, Aurélien Plazzotta via
Digitalmars-d-learn wrote:
 On Tuesday, 18 June 2019 at 09:17:09 UTC, Bart wrote:
 
 Can someone help me understand this a little better and how I'd go
 about using it in D? Specifically I'm looking at the pros and cons,
 what are the real similarities and differences to oop, and how one
 implements them in D(taking in to account D's capabilities).
[...]
 Perhaps, you should be interested by this article written by our
 famous Walter:
 http://www.drdobbs.com/architecture-and-design/component-programming-in-d/240008321
 
 You'll get a whole new idea about reusability :)
<shameless self-plug> And also: https://wiki.dlang.org/Component_programming_with_ranges </shameless self-plug> T -- English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
Jun 18 2019
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 18 June 2019 at 09:17:09 UTC, Bart wrote:
 I'm new to component based programming. I've read it is an 
 alternative to oop for speed.
Component based modelling is part of the OO-modelling toolbox. Also, it isn't new, e.g. database-oriented modelling techniques often use the same philosophy (e.g. SA-modelling and ER-modelling predates object-oriented-modelling). It isn't about speed, it is about being able to combine independently written frameworks (or components) using an id as an identifier for an entity. It also helps when your implementation spans over many computers (or services). So basically, if you have an independently written hotel-reservation component, a golf-course component, a flight ticket component and so on, then you can compose this to a full "vacation system" by combining the various components. Nothing new about this, but it got traction around 15-25 years ago as software got expensive to build from scratch (as programs grew larger) and you want to develop a framework of prewritten components that can be combined for easier and cheaper production. So in that respect you probably, in most cases, trade performance (slower) for easy reuse and easier debugging (in some cases). In the game community they claim to do it for performance reasons, but that is probably not the case, it is again about costs of doing multithreaded programming and splitting the codebase into specialized chunks that different teams can work on for good performance on individual parts. So yeah, the claim is "speed", but there is no real substance to that claim, in the general case. Speed isn't a result of the generic modelling-strategy. But in some scenarios it might be easier to partition the design into components and make each component perform well than doing it as a monolithic design. Although in theory the monolithic design should always perform better if done in an optimal fashion. The problem is that it is too expensive to do an optimal monolithic multi-threaded design well (and change becomes difficult). E.g. the most high performing OS-kernels are monolithic for performance reasons. However, the development costs of that approach are prohibitive for ordinary software (even games).
 Can someone help me understand this a little better and how I'd 
 go about using it in D? Specifically I'm looking at the pros 
 and cons, what are the real similarities and differences to 
 oop, and how one implements them in D(taking in to account D's 
 capabilities).
It has precious little to do with the programming language. It has more to do with modelling. So you probably will learn more from looking at component based modelling as a tool in your OO-modelling toolbox than following a particular implementation of a component based design. Unless you want to write games, in which case you should look in that direction. (e.g. reuse an existing physics component). Ola.
Jun 19 2019