When designing both the domain-model and class-diagrams I am having some trouble understanding what to put in them.
I'll give an example of what I mean:
I am doing a vacations scheduler program, that has an Administrator and End-Users. The Administrator does a couple of things like registering End-Users in the program, changing their previleges, etc. The End-User can choose his vacations days, etc.
I initially defined an Administrator and End-User as concepts in the domain-model, and later as classes in the class-diagram.
In the class-diagram, both classes ended up having a couple of methods like
Administrator.RegisterNewUser();
Administrator.UnregisterUser(int id);
etc.
Only after some time I realised that actually both Administrator and End-User are actors, and maybe I got this design totally wrong. Instead of filling Administrator and End-User classes with methods to do what my Use-Cases request, I could define other classes from the domain to do them, and have controllers handle the Use-Cases(actually, I decided to do one for each Use-Case). I could have a UserDatabase.RegisterNewUser() and UserDatabase.UnregisterUser(int id);, for example, instead of having those methods on the Administrator class.
The idea would be to try to think of the whole vacation-scheduler as a "closed-program" that has a set of features and doesn't bother with things such as authentication, that should be internal/protected, being that the only public things I'd let the outside world see would be its controllers.
Is this the right approach? Or am I getting this totally wrong? Is it generally bad idea to put Actors in the domain-model/class-diagrams? What are good rules of thumb for this?
My lecturer is following Applying UML and Patterns, which I find awful, so I'd like to know where I could look up more info on this described actor-models situation.
I'm still a bit confused about all of this, as this new approach is radically different from anything I've done before.
I would not say that your design, as you speculate, is totally wrong, in fact Administrator and End-User are valid domain objects that should be represented somehow in the Class Diagrams. Just because you identify those two entities as actors doesn't mean they should be excluded from the Domain, remember, your domain is your scope, or "relevant context", that is, the set of useful objects that play a relevant role in your solution.
You may start with basic objects that comprise your model, just write them down, without further analysis, like brain storming...
Vacation
Location
Travel Agent
Schedule
User
Reservation
Reservation Service (This can be an interface for accessing the vacation reservation stuff)
Then try to establish the relationships between those objects, if you can not find any relationship that means you are not choosing the right objects, if they are part of the same problem domain then they must be related somehow.
After some time, you will discover that there are objects missing, try to encapsulate as much as possible, and represent the correct abstractions, Design Patterns might help you out with that.
When every possible object is represented with all its properties and methods, then you should have a fully, although not yet finished, functional design.
I know you should have a lot of theory in your mind, so get going, without fear, I myself have used this approach successfully many times at work.
Finally get a copy of UML Distilled
Regards,
I think you should learn more about domain modeling and process of getting from use cases to class diagrams. Actors as classifiers can be part of class diagrams, however for class diagrams used for analysis and design are modeling the system you develop and an actor is external entity. When you are using use cases and use case diagrams, the goal is to identify functional and non-functional requrements, therefore define the scope of the system to develop and external entities - roles or systems - interacting with the system you are developing. In use case diagrams you can find sometimes a box representing system boundary, which encompasses all use cases, which will be realized in your system, but actors are out of the box. When domain modeling, you usually forget about the system altogether, because you want to capture the way the domain works. Often special diagrams and modeling elements are used for domain modeling. As I said, the point is to understand the domain in which the system will be used. Class diagrams in the analysis and design phase describe the system you are developing, so no actors can be inside.
Related
Hi after creating a button in HTML in Visual studio, how can i do its backend c# coding? Normally while using webforms double click will open coding class but how to acheive this in Visual studio for HTML element?
I think you can use the MVC pattern. To be more familiar with, you can read this documentation https://www.asp.net/mvc.
Few words about MVC pattern:
Define MVC in layman’s terms
Remember you’re technically minded and close to the code. MVC to you
is as clear as day, but saying to the business ‘Model, View,
Contoller’ could give them the impression that you are suffering from
some form tourette syndrome. MVC won’t mean much to the business even
after you define them in relation to the code. To get the business to
understand why this is the answer and least of all what it is, can be
more of a task than expected in my experience. Even some fellow
developers have difficulty understanding this on occasion.
To get the listener to understand what MVC is and why it works what I
have tried in the pass is to apply MVC to a different industries where
the listeners have had more involvement. An example that has worked
for me in the past in a comparison to the property or even the
vehicles. Most people have had dealing’s with builders, carpenters,
plumbers, electricians or have watched the flood of property shows on
the TV. This experience is a good platform to use and to explain why
separation such as MVC works. I know you’re probably thinking that
won’t work as it’s not the same as in software, but remember you’re
not trying to train the business to become developers or have an in
depth understanding of MVC, simply explaining to them that separation
in production is required and that’s what an MVC structure offers.
To give an example of how you could describe this I have very briefly
explained how separation works in property. Keep in mind this is
focused on using the system not developing which could be a completely
different angle of explanation.
View
The view in MVC is the presentation layer. This is what the end user
of a product will see and interact with. A system can have multiple
views of all different types ranging from command line output to
rendered HTML. The view doesn’t consist of business logic in most
clear designs. The interface is fit for purpose and is the area of
interaction. Therefore you could simply output HTML for consumers to
interact with or output SOAP/XML for businesses to interact with. Both
use the same business logic behind the system otherwise known as the
models and controllers.
In the world of property you could think of the view as the interior
of a property or the outer layer of a property that the inhabitants
interact with. The interior can be customised for purpose and the same
property can have many different types of tenants. For example a
property of a particular design could contain residential dwellings.
The same internal space could easily be used as office space, where
although in the same property has a different purpose. However the
property structure is the same. Therefore the environment in which the
users interact does not interfere with the structure of the building.
Controllers
The controller is where the magic happens and defines the business
application logic. This could be where the user has sent a response
from the view, then this response is used to process the internal
workings of the request and processes the response back to the user.
Taking a typical response where a user has requested to buy a book.
The controller has the user id, payment details, shipping address and
item choice. These elements are then processed through the business
logic to complete a purchase. The data is passed through the system
into the model layer and eventually after the entire request satisfies
the business definitions, the order is constructed and the user
receives their item.
If we compare this to a property, we could compare the ordering of a
book online to turning on a light switch. A tenant will flick the
switch to on just like ordering a book. The switch itself is an
element in the view layer which sends the request to the controller
just like clicking a checkout button on a web site. The business logic
in this case is what the electrician installed and are embedded within
the property designs. The switch is flicked, which completes the
circuit. Electricity runs through all the wires including the fuse box
straight through to the light bulb. Just like the user receiving a
book, in this case the tenant receives light. The whole process behind
the scenes involving the electricity cabling is not visible to the the
tenant. They simply interact with the switch within the space and from
there the controller handles the request.
Models
The models in MVC are the bottom most layer and handle the core logic
of the system. In most cases this could be seen as the layer that
interacts with the data source. In systems using MVC, the controller
will pass information to the model in order to store and retrieve
data. Following on from the example above controller definition, this
is where the order details are stored. Additional data such as stock
levels, physical location of product of the book amongst many things
are all stored here. If that was the last book in stock ordered, the
next request for this item may check if it’s available and disallow
the order as the item is no longer available.
Sticking with out example of turning on a light switch, this level in
our structure could be the electricity supply. When the tenant flicks
the switch, the internal circuit must request electricity to power the
request which is similar when the user requested data from the
database, as in data is needed to process a request. If the dwelling
isn’t connected to an electric supply, it cannot complete the process.
Business benefits from using MVC
After you get the message across explaining what MVC is, you will then
have to see what benefits can be obtained from it. I’m not going to go
into a huge amount of detail here are I’m sure you can apply benefits
more accurately which are directly related to you actual situation. To
list just some of the common benefits of an MVC based system here are
a few examples:
Different skill levels can work on different system levels. For example designers can work on the interface (View) with very little
development knowledge and developers can work on the business logic
(Controller) with very little concern for the design level. Then they
simply integrate together on completion.
As a result of the above separation projects can be managed easier and quicker. The designer can start the interfaces before the
developer and vice versa. This development process can be parallel as
opposed to being sequential therefore reducing development time.
Easy to have multiple view types using the same business logic.
Clear route through the system. You clearly know where there different levels of the system are. With a clear route of the system,
logic can be shared and improved. This has added security benefits as
you clearly know the permitted route from the data to the user and can
have clear security checks along the route.
Each layer is responsible for itself. (Relates to point 1) This means that you can have clean file structure which can be maintained
and managed much easier and quicker than a tightly couple system where
you may have lots of duplicate logic.
Having a clear structure means development will be more transparent which should result in reduced development time,
maintenance problems and release cycles if applied properly.
Source: http://www.strongandagile.co.uk/index.php/a-really-simple-explanation-of-mvc/
Another option is keep programming using WebForms, for that, you have to choose the right application:
I have a a broad-scoped architecture question. I have multiple .net projects and multiple databases all interacting with each other across multiple web applications all for internal use. We would like to create an over-arching layer, somewhere, somehow, to create objects out of the data we query from a database. These objects would have functions/methods available to them, defined somewhere. The question is, what is the most efficient, flexible and advantages/disadvantages of way to define these objects.
For example. Let's say I have multiple HR-related tables: tbl_employees, tbl_departments. When I pull an employee into an application, I then have a whole bunch of code in that project that is associated with that employee, most predominately the functions I can do to that employee - functions such as edit_contact_info or increase_salary or add disciplinary_note. Similar with a department and functions such as edit_department, manage_department_employees. Some functions may include some logic in them, some may just redirect to a particular page.
My question is, how or where or what can I make to classify an employee entry or even series of employee entries as an "object", meaning whenever I pull that "object" somewhere, I also have the associated actions with it. Whether I am pulling the data as a list somewhere or even as part of a data-visualization, I would like to have the appropriate functions/methods available. Even if it is in a different project.
I am looking for different possibilities, not necessarily one answer and I am not entirely sure the best way to go about it although I have thought maybe about creating another layer within the database that holds all the "object" definition data or perhaps some definitely with the .net framework but I lack the expertise to know exactly what I am talking about. From my limited knowledge, I believe I am looking for some sort of ORM (maybe in-memory) implementation, but I am not sure how to get started exactly.
Does anyone have any ideas or a direction to point me in perhaps?
I appreciate any and all help!
Edit
To be clear, what I am trying to find is something I can apply on top of projects and applications I already have up and running and that are being used. I would like a way to implement this over-arching object functionality on top of pre-existing mvc projects
I'm new to DDD and I am working on my first project, which is for an online golf outing registration process. my requirements are pretty simple. users register for the outing and can optionally add a foursome. they can also sponsor a hole with a message and a few other things, but i want to hash our the foursome stuff first.
so, my first though my aggregate contains the a registration entity, foursome value object (which contains a team name and 4 player value objects).
when designing the api, i'm thinking the following pseudo code:
Registration reg = new Registration();
Foursome foursome = reg.CreateFoursome("My Team");
foursome.Player1.Assign("John Doe", 5, ShirtSize.XL);
reg.Register();
My question is, one of the internal components of the aggregate is being exposed to the client code, so am I opening my self up for issues? any flaws with this simple design or alternative apis?
any help would be great as i am in a state of analysis paralysis right now!
thanks
Lets start with Aggregate definition:
A cluster of associated objects that are treated as a unit for the
purpose of data changes. External references are restricted to one
member of the Aggregate, designated as the root. A set of consistency
rules applies within the Aggregate's boundaries.
Aggregate is a group of objects that you would not want multiple users to edit at the same time because it can break domain invariants. Aggregate is also a life cycle unit. It is hard to answer your question without knowing what these invariants, consistency and life cycle rules are. Would creating two Foursomes on the same Registration be bad? Would Foursome with unassigned Player1 be invalid/inconsistent? Would not calling Register on Registration object will 'corrupt' it? If one of the the answers is true then you should not expose your objects like that. This code should be hidden inside your aggregate.
It also looks like Foursome is not a Value Object because it is mutable. It maybe an entity that should be protected by Registration aggregate root.
// PlayerInfo is a value object
public static Registration CreateNew(String foursomeName, PlayerInfo player1, ...) {
if (foursomeName == null) {
throw new ArgumentNullException("foursomeName");
}
if (player1 == null) {
throw new ArgumentNullException("player1");
}
Registration reg = new Registration();
Foursome foursome = reg.CreateFoursome("My Team");
foursome.Player1.Assign(player1);
if(player2 != null) {
foursome.Player2.Assign(player2);
}
reg.Register();
// return consistent and valid Registration instance
return reg;
}
Again, this can be not what you want, it really depends on your domain model. Maybe your Aggregate root should be an entity like FoursomeRegistartion. Maybe Players are aggregates themselves if they can exist outside Foursome/Registration boundary. As others have said, it is hard to get model right the first time. Have a first implementation and refactor continuously.
For a first shot it isn't bad. It is important when starting design not to get too hung up on the small details. How much time you spend worrying about the robustness of the design is going to be primarily a factor of the project's importance. You will continually learn as you build, and over time, your old code will require refactoring to enable new details.
Take for instance, your FourSome class I assume has four players. Could you instead have a Team class which has a Size constraint, such that a Players collection could be constrained to that number of players? Should there be a Player class (or perhaps that is the type of Player1?)?
The answers to these questions will have implications toward the extensibility of your system.
I encourage you to write each of your scenarios into tests (you could use user stories or use cases too, but developers like to write code), and as you write the tests, fill in the Registration, Player, and Foursome/Team class implementation to make the tests succeed. As you expand your system, your tests will change, and so will your design.
Post Addition 1:
Domain driven design is intended to be an approach to developing the classes and data structures your application will use such that it "models" the problem domain. In your case, you are working with a Golf Outing Registration system. Therefore, as you think about the entities which might make up such a system, you might describe how a Team Captain registers his/her Team (including other Players) by providing his Registration. The registration might be for an Event, which itself may have details such as Organizer, Sponsor, etc. As you see, each of the "capitalized" names become your entities (classes). At least for the first draft of your design. As you discover more information about the relationships between your classes, especially in how they interact (a Player is added to a team), you will flesh out the methods of your class.
During this process you can inadvertently introduce design flaws. For instance, a FourSome is, technically, a type of Team limited to four players. Does it make sense to derive a class from Team and set a limit of four players, or does it make sense to put a constraint on Team? That is a design decision determined by... your business rules and you. Is it a mistake to take one approach over the other? Time will tell, as you will need to constantly refactor in order to expand the system.
You will find many patterns during your design process that may make your design process easier, but a new designer typically does not have the experience to recognize when to use them. If you do, kudos to you. You will not find a perfect design the very first time you are designing. I still look back (15 years now) at designs I thought were awesome, and shake my head at my youthful exuberance.
You should describe your problem (to yourself or on paper). Underline the nouns. They are your candidate classes. Tell a story for each user interaction with the system, and the verbs should get you started toward what the methods are on each class. Avoid using the Registration to do all the work, but separate the responsibility of the classes to where it is appropriate. For instance, you can add a player to a team, or you can have a player add itself to a team. Determining where that responsibility lies should be guided (but not dictated) by the SRP, among other design guidance.
Finally, there is no right answer in design. I could tell you based on my extensive design experience but limited golf experience what I THINK it should be, but ultimately your best design depends on the features, scope, and design goals (like extensibility). Start with your best shot, write tests against it, and your design flaws will emerge before you know it. :D
Post-Revision 2:
I think you are reading too much into Eric Evan's guidance. I don't believe he is saying that you can't expose Player from Foursome.
In some projects I see that a dummy record is needed to create in Db in order to keep the business logic go on without breaking the Db constraints.
So far I have seen its usage in 2 ways:
By adding a field like IsDummy
By adding a field something called ObjectType which points a type: Dummy
Ok, it helps on what needs to be achieved.
But what makes me feel alert on such solutions is sometimes you have to keep in mind that some dummy records exist in the application which needs to be handled in some processes. If not, you face some problems until you realize their existence or until someone in the team tells you "Aha! You have forgotten the dummy records. You should also do..."
So the question is:
Is it a good idea to create dummy records to keep business logic as it is without making the Db complain? If yes, what is the best practice to prevent developers from skipping their existence? If not, what do you do to prevent yourself from falling in a situation where you end up with an only option of creating a dummy record?
Thanks!
Using dummy records is inferior to getting the constraints right.
There's often a temptation to use them because using dummy records can seem like the fastest way to deliver a new feature (and maybe sometimes it is), but they are never part of a good design, because they hide differences between your domain logic and data model.
Dummy records are only required when the modeller cannot easily change the Database Definition, which means the definition and/or the data model is pretty bad. One should never end up in a situation where there has to be special code in the app layer to handle special cases in the database. That is a guaranteed maintenance nightmare.
Any good definition or model will allow changes easily, without "affecting existing code".
All business logic [that is defined in the Database] should be implemented using ANSI SQL Constraints, Checks, and Rules. (Of course Lower level structures are already constrained via Domains/Datatypes, etc., but I would not classify them as "business rules".) I ensure that I don't end up having to implement dummies, simply by doing that.
If that cannot be done, then the modeller lacks knowledge and experience. Or higher level requirements such as Normalisation, have been broken, and that presents obstacles to implementing Constraints which are dependent on them; also meaning the modeller failed.
I have never needed to break such Constraints, or add dummy records (and I have worked on an awful lot of databases). I have removed dummy records (and duplicates) when I have reworked databases created by others.
I've never run across having to do this. If you need to do this, there's something wrong with your data structure, and it's going to cause problems further down the line for reporting...
Using Dummies is dumb.
In general you should aim to get your logic right without them. I have seen them used too, but only as an emergency solution. Your description sounds way too much like making it a standard practice. That would cause more problems than it solves.
The only reason I can see for adding "dummy" records is when you have a seriously bad app and database design.
It is most definitely not common practice.
If your business logic depends on a record existing then you need to do one of two things: Either make sure that a CORRECT record is created prior to executing that logic; or, change the logic to take missing information into account.
I think any situation where something isn't very easily distinguishable as "business-logic" is a cause for trying to think of a better way.
The fact that you mention "which points a type: Dummy" leads me to believe you are using some kind of ORM for handling your data access. A very good checkpoint (though not the only) for ORM solutions like NHibernate is that your source code VERY EXPLICITLY describes your data structures driving your application. This not only allows your data access to easily be managed under source control, but it also allows for easier debugging down the line should a problem occur (and let's face it, it's not a matter of IF a problem will occur, but WHEN).
When you introduce some kind of "crutch" like a dummy record, you are ignoring the point of a database. A database is there to enforce rules against your data, in an effort to ELIMINATE the need for this kind of thing. I recommend you take a look at your application logic FIRST, before resorting to this kind of technique. Think about your fellow dev's, or a new hire. What if they need to add a feature and forget your little "dummy record" logic?
You mention yourself in your question feeling apprehension. Go with your gut. Get rid of the dummy records.
I have to go with the common feeling here and argue against dummy records.
What will happen is that a new developer will not know about them and not code to handle them, or delete a table and forget to add in a new dummy record.
I have experienced them in legacy databases and have seen both of the above mentioned happen.
Also the longer they exist the harder it is to take them out and the more code you have to write to take into account these dummy records which could probably have been removed if you just did the original design without them.
The correct solution would be to update your business logic.
To quote your expanded explanation:
Assume that you have a Package object and you have implement a business logic that a Package without any content cannot be created. YOu created some business layer rules and designed your Db with relevant constraints. But after some years a new feature is requested and to accomplish that you have to be able to create a package without a contnent. To overcome this, you decide to create a dummy content which is not visible on UI but lets you to create an empty package.
So the at one time to a package w/o content was invalid thus business layer enforced existence of content in a package object. That makes sense. Now if the real world scenario has changed such there is now a need VALID reason to create Package objects without content it is the business logic layer which needs to be changed.
Almost universally using "dummy" anything anywhere is a bad idea and usually indicates an issue in implementation. In this instance you are using dummy data to allow "compliance" with a business layer which is no longer accurately representing the real world constraints of the business.
If package without content is not valid then dummy data to allow "compliance" with business layer is a foolish hack. In essence you wrote rules to protect your own system and then how are attempting to circumvent your own protection. On the other hand if package without content is valid then business layer shouldn't be enforcing bogus constraints. In neither instance is dummy data valid.
I'm working on a kind of a HMI application and is creating objects to define a specific machine. Lets say this is a car for the sake of argument.
A object for the engine is obvious. There are a few common sensors on the engine, and this is a few objects mounting to a few properties on the engine object. The throttle property is a input of course.
The car has atleast one door. Each door can have a window, it can be openable and it may be electrically operated. If it's electrically operated it will depend on power from the car to operate.
Now, should I expose the door as a property on the car object, or would it be most sensible to keep it private and having the car object operate the door in OpenDoor and RollDownWindow functions? What about events? Should I expose events on the engine, example LowOnOil event, or should I deal with it in the car object witch in turn could have an event like EngineIsLowOnOil?
How would you do this?
This, and all similar questions, can be answered by considering why you are building the model. There is absolutely no point in creating a model in isolation from the problem you are trying to solve, and in general it is not possible to do so.
For example, if you are building an electronic fuel injection control, system, the number of doors on the car (and posibly even the car itself) is of no interest, and should not be modelled.
Let us explore a little your example of opening the door of a car (say the front left). One could take several approaches (including those which you suggest):
Car.OpenFrontLeftDoor
Car.OpenDoor(FRONTLEFT)
Car.Door(FRONTLEFT).Open
Car.Part(DOOR_FRONTLEFT).Open
Car.Part(DOOR_FRONTLEFT).DoAction(OPEN)
None of them is right or wrong, it depends on the situation. I am sure there are many more ways too.
Number 1 is very much a hard-coded function approach. This would be good for very simple, fixed situations. But it would become unmanageable if your model needs to accomodate variation.
Number 5 is taking a parameterised approach. The latter is a lot more flexible and requires a greater design nous to pull off but could be overkill for a simple problem.
Also bear in mind that your car object can present an external interface different to the internal implemenation. For example, you could use approach 5 internally but present an interface such as in 1, and translate the function calls under the hood (no pun intended).
Ultimately the ability to make decisions like this comes from experience. Expose yourself to good OO design, read books, examine the source code of good software. And above all, try different designs out and see for yourself what works and why.
Einstein said "Make it as simple as possible, but no simpler."
Start with an empty object. As you develop the entire model, add to the object only those attributes that are NECESSARY.
I think this is a very generic question that is hard to answer. My best answer would be "It depends on your needs and the problem domain you are trying to solve".
In the scenario you have given I usually tend to think about it in a real life situation.
So the door is not private to the car i.e. the door of the car is publically accessible. The car does not open the door (unless it is a pretty cool car!) a User would open the door. Hence the door should probably be a public property of the car.
In terms of exposing the events, it really depends on whether you intend on handing them. For example, the OnLowOil event is probably an event you would want to be handled i.e. notify the user who would then perhaps do Car.Engine.FillOil
If in doubt, consider the problem from a different approach: "How would I test these objects?" "How would I test the window?" "What would make testing easiest?" Being a lazy programmer, that's a very important question for me to answer. I want writing the tests to be dirt simple, yet highly effective in proving that my code works.
In your case, you have a car with doors that can open and close, and the doors have windows that can open and close, and they may or may not be electrically operated. How would you test the "window-down" function? Is the window's existence dependent upon the engine? Is it even dependent on the car, or is it really dependent only on the door? Do different doors have different shaped windows with different rules or different amounts of travel? Do different doors use identical electric motors to drive the windows, or are the window motors different for left-mounting versus right mounting?
And consider that a customer may give you a requirement that says "the windows only work when the engine is running", but is that really true? In most cars the windows work when the car's power switch is turned to "on". Put another way, is the window operation dependent on a spinning crankshaft in an engine, or is it actually dependent on 12 volts of electricity? So do you really need an engine instance in a car to test a window, or do you just need a battery?
Once you start asking those questions, you're likely to conclude that a power window is deserving of its own set of tests (up/down/part-way/full-travel/etc.), so it becomes a good candidate for being its own class. The number of different doors might be complex, so you figure a "door factory" might be an appropriate class to create that can manage all the different kinds of doors. Testing things in isolation is always easier: look at the harder questions about what the engine throttle setting should be to test the window-up function? What about the transmission gear, or the door open/close state? All these permutations make it hard to test, even though they have no bearing on whether the window works or not. So all these lead me to think the window classes should be tested standalone as much as possible. In the real world, you'd only need 12 volts to test a power window mounted in a door. So in your modeled world, you'd only need a mock or fake power supply object to provide the modeled power, not an engine object or a transmission gear. It's a simpler test.
After you take those sorts of ideas into consideration, you start realizing that passing dependencies in the tests (here's a power supply for the window test) makes them easy to test; thus the way to assemble the real components in your model would mean encapsulating construction in factories would make for the easiest way to create your car; so building the car might suggest the abstract factory pattern be used to inject all the dependencies into the car.
You might even start with a simple-but-brittle Car class with a hard coded Engine and hard coded Doors, and then refactoring it to add tests like those above. You would likely still end up with independent Car, Door, and Window objects, and an abstract factory pattern to create them all based on the model of car being built. This idea is called "emergent design."
I like to keep things simple. In your Domain/Objects think of how you would speak about the object to determine what way to model it, would you say my car needs oil or my car's engine needs oil?
It depends on the domain. The Domain for a car factory would refer to cars differently than a car rental Domain.
I would have numberous window properties for each window and events off them, and a window state/position as well.
There are no right or wrong models; there are models that are more or less useful for your specific purpose.
As others have said, think first on what information is relevant to your needs. And then discard the rest. That process of removing unnecessary detail is called abstraction. If we didn't perform abstraction, our models would be identical to the real-world entities that they represent! Which would be useless, since the ultimate goal of modelling is obtaining a simplified version of reality that allows us to reason about it in its absence.
I think there are several people here making the same point, but I will try again.
You are asking questions like should I or should I not expose "Door Opened" event. There is no answer to this question other than with another one: how are you going to use it
Ultimately the model is the means not the goal and as such the model cannot be defined outside the context. Even (especially) if you are building your model to sell it as a standalone product you have to think how your customers will use it which - again - is a discussion about context.
Trying answering such questions based one anything else (gut feel?) will be an exercise in counting demons on the end of the needle