I must structure new model for application and I don't what is better:
using inheritance or using enum as type of object:
For example :
Books
class Book
{
public string Name {get;set;}
public string Author {get;set;}
public int NumberOfPages {get;set;}
}
public class Encyclopedie:Book
{
}
public class Novel:Book
{
}
or better use:
class Book
{
public BookType Type {get;set;}
public string Name {get;set;}
public string Author {get;set;}
public int NumberOfPages {get;set;}
}
public enum BookType
{
Encyclopedie = 0,
Novel = 1,
...
}
Use inheritance if the different types have significant differences (how you process them and treat them). That is, if you are going to use polymorphism at all, you should use inheritance.
If you only need a way to distinguish different types of books, go with the Enum.
In true object oriented systems, the type of the object is transparent to the client. So the code which handles books should not know what the type of the book is, but only invoke methods on books.
So if you need to implement different behaviour within the book in response to the method invocation, extend Book and override some of its methods. If you don't, then don't.
It appears, given the empty bodies of your subclasses, that they behave in every way the same as books. So you are merely tagging the book with some additional data - the difference between Encyclopaedia and Novel is no more essential to the book than hardback or softback or large print or standard print - a client may use these differently, and each book either is a large print book or it is a standard print book, but these are all attributes of the book rather than essential differences.
I wouldn't necessary use an enum for the book kind, since you may want to add more data - I'd either use a loose tagging system, so you can tag a book with a collection of kinds - so you would have a book tagged as { 'children's', 'ornithological', 'encyclopaedia', } - or allow structure in the roles - so there is a role for 'children's ornithological encyclopaedia' created when it is required, but no fixed enumeration.
I would say that the 2nd would be better as you are not really extending the book class in your Encyclopaedia, there are no additional properties or functionality you need to give one book type over another.
"best" is subjective and heavily depending on the purpose of the class / model.
What is your goal? What do you want to achieve?
At best at this point I can say is, inheritance is useful when the derived class has some fairly unique properties - like Encyclopedie has properties explaining which type of Encyclopedie it actually is and those properties do not, in any way, belong to a novel.
It really depends. The first solution is better if you need to use Polymorphism. From my personal opinion, I prefer using inheritance.
If the different types of books will have different attributes you should definately use an inheritance model. This also allows for polymorphism, which is usually better
If they will all have the same attributes, you might as well go with the enum. But it all depends on the application.
I think you should make this choice based on what the book "purpose" is. If the books don't need any additional stuff (methods and properties....) enum should be enough. If you have to create a common behavior for every book and something else more specific for each book type you obviously need inheritance (abstract class "book", and concrete classes).
using an enum to "type" your object sounds a bit of "old C-style" programming.
I mean, it is ok, but when inheritance is available (you're using C#) it is generally a better choice. An enum generally introduces some "trouble" for example when serializing/deserializing data: what if an old version of your application uses a "newer" scenario in which a BookType has an unknown item? (backward/forward compatibility could be a requirement for your app)
Of course, you can handle this with a bounch of "if-then-else" but inheritance seems a cleaner choice in my point of view.
Bye!
Related
A course can have multiple activities, i.e. Training, Exam, Project, Book, Article, and Task.
Following are the requirements:
Allow the teacher to schedule a course.
Allow the teacher to schedule different activities in the said course.
Display list of activities to the student for a selected course, in a specified date range.
The above requirements lead me to create two aggregates.
CourseAggregate
ActivityAggregate
Why?
A course can be created without any activities, but only in draft state. A course can be scheduled on for a different set of students.
An activity can be created independent of course, and later on, linked to a course.
Activities can be fetched with a date range only for a given student.
protected abstract class Activity
{
public Guid Id {get; private set;}
}
protected class Training : Activity
{
..... Addiontal properties
}
protected class Exam : Activity
{
....Addiontal properties and behavior.
public bool AllowGrading => true;
}
.... Other childern of activity..hence more classes.
Questions:
Is it the right approach to go with inheritance?
Since I marked the constructor protected, so the client code will not use the new operator, and will not have direct knowledge of children. I am struggling to figure out how the client should create an instance of the activity. For example:
[Test]
public void ActivityFactoryShouldCreateCorrectActivityType(){
var activity= ActivityFactory.CreateActivity(activityType:"Training", title:"Training", DueDate: "date".......)
}
Problem is, each subtype might want to enforce different invariants for the entity to be correctly created. For example, Exam activity requires information about the scale of grading.
How to solve correctly implement it or which pattern suits better here?
That is one of the problem that frquently pops up when using a language like C# or Java. That is an implementational problem more than it is modeling issue.
The thing is that you do have these concepts: Exam, Training etc. that are concrete. On the other hand you can derive a common concept for them: Activity.
Here are couple of questions that we need to ask before we consider an implementation.
What it needs to do with these concepts?
How does it works with them?
How many parts of the system are interested in the concrete concepts Exam, Training etc. and how many of it is interested in the common concept of Activity?
Do you expect to add many more concepts that will be Activities? This will affect how you evolve your system.
Let's say that your system doesn't use the concept of Activity much and it wont have many more activities added. In this case we can just ignore Activity and just use concrete concepts. This say there is no problem in creating them.
Let's say that your system will use the concept of Activity and you need to add more types of activities.
This doesn't undermine the fact that your system will know of the different concrete types of activities. It will create them, work with them etc. Even when your system is working with the concept of activity it will probably still need to know the concrete type of the activity so it can do something with it.
This kind of logic shows a problem with the way that we think when we use an OOP language like C# of Java. We are trained as developers. usually people say that casting is bad. You sould somehow define a base class or an interface and let subclasses of interface implementers define a behavior and the other parts of the system shouldn't know the concrete type.
And this it true for some parts of the system and for come concepts. Take for example a Serializer. You can define an interface ISerializer with a method Serialize. The system that uses a serializer may use the interface without having to know the concrete type as each class that implements the ISerializer interface will add a different implementation of the same interface.
Not every problem is like that. Sometimes your system needs to know what it deals with. This is where i thing we can learn something from languages like JavaScript. There what you have is an object that is non specific and use can just attach properties to it. The object is what it's properties define it to be.
The concept of Duck Typing is interesting: "If it walks like a duck and it quacks like a duck, then it must be a duck"
If you system needs to work with Exam it should work with it not with an Activity. If it has an Activity it should be able to figure out it it's indeed an Exam because this is that it needs.
Now we live in the strong typed world and it has it's good parts. I love strong typing and what it gives you, but also some problems are more difficult to deal with.
You can use classes with inheritance to implement this. You also use interfaces instead of having classes to capture different concepts. Yet your system will need to do some casting to determine the concrete type of what is working with. We can make it's life a bit easier if we capture the fact that we have different types of Activities explicitly
Here's an example:
public enum ActivityType { Exam, Trainig, Project, Task }
public class Activity {
public Guid ID { get; private set; }
public abstract ActivityType Type { get; }
// other stuff
}
public class Exam : Activity {
public override ActivityType Type {
get { return ActivityType.Exam; }
}
// other stuff
}
public class SomeClass {
public void SomeAction(Activity activity) {
if(activity.Type == ActivityType.Exam) {
var examActivity = (Exam)activity;
// do something with examActivity
}
}
}
If creating your activities have some logic related to them you can use a Factory to create them by using their concrete types.
public class ExamFactory {
public Exam CreateSummerExam(string name, //other stuff) {
// Enfore constraints
return new Exam(new Guid(), name,....);
}
}
Or add a Factory to the concrete type:
public class Exam : Activity {
public static Exam CreateSummerExam() {
// Enfore constraints
return new Exam();
}
private Exam() { }
}
Or just use a public constructor if creating these objects is not complex.
If you realy want to hide the classes to allow yourself some freedom of implementation then use interfaces:
// **Domain.dll**
public enum ActivityType { Exam, Training }
public interface IActivity {
ActivityType Type { get; }
}
public interface IExam : IActivity { }
internal class Exam : IExam { }
public class ActivityFactory {
public IExam CreateExam() { return new Exam(); }
public ITraining CreateTraining() { return new Training(); }
// other concrete activities
}
This way you don't allow clien code to have access to classes. You can give them access to public interfaces and keep other implementation specific methods internal to your Domain.dll. Clients of these concepts can still use casting to use the appropriate type that they need, but this time they will use interfaces.
Here's a good article on this. In it Martin Fowler says:
With OO programs you try to avoid asking an object whether it is an
instance of a type. But sometimes that is legitamate information for a
client to use, perhaps for a GUI display. Remember that asking an
object if it is an instance of a type is something different than
asking it if it is an instance of a class, since the types
(interfaces) and the classes (implementations) can be different.
EDIT:
Another implementation of this is to treat an Activity as a container that you can attach different things to it. This will give you a more flexible system. Unfortunately this won't remove the need for switching and checking if various features are present in your entity. It's possible to some degree but depending on your concrete case you may need to process an Activity from some external component and will need to swith and check.
For example you may want to generate some report. You may need to get some activities, process them and then generate some report based on some data stored in them. This cannot happen with attaching components to one activity as this operation requires multiple activities not a single one.
There are a lot of systems that do this kind of thing. Here are some examples:
Computer Games use something that is called Entity Component System.These systems are data oriented where an Entity is comprised of different Components. Each system then checks to see if a Component is attached to an Entity. For example you have a Rendering system that renders your scene with all players and stuff. This system will check if an entity has attached 3D model component. If it has it will render it.
The same approach is used in Flow Based Programming. It is also data driven where you send Information Packets that are composed of different properties. These properties can be simple or complex. Then you have Processes that are connected and pass data between each other. Each Process will search for specific type of data in a IP to check if it's supported by it.
Unity also supports using Entity Component System. But it also supports another similar approach to having active components that contain behavior and logic instead of passive data that is processed from external systems.
Feature based programming. Uses the notion of features that you can add to an object. It's used in CAD/CAM system, banking systems and many more
It's a good approach to use when having dynamic data that needs to be processed. Unfortunately this won't remove the need to do some if/else and swich. As already mentioned, when you need to process collections of Activities you will need to do some checking.
Note that the systems above don't try to avoid this. On the contrary. They embrace this fact and use dynamic data. It's no different then having a type fo the activities and switching on it. It's just that their approach give a more flexible system at the expence of doing a lot of checks.
If you system doesn't require that kind of dynamic data you can just use concrete classes instead of data objects that can store unlimited number of things. This will simplify some parts of your application. If you do need to compose different objects then you can use one of the approaches above.
Thank for taking the time to answer the question in detail & with beautiful insights.
Consider we are developing https://coursera.org site. There are two major high-level goals which system has to achieve.
- Teacher/Course Creator should be able to create (schedule) a Course. From creator point of view, he/she want to add Exam, training or other activities to course. But he/she will refer to it as "I am scheduling an exam activity in this course for the following dates, with the following criteria of fail/pass" or "I am scheduling a training activity, in this course." Now, if we go with IActivity interface approach along with ActvityType Enum, all the client code, will be using switch or if/else to see what type of activity it is, and this will flow to top-level i.e. UI, or even controllers or consumer classes,
if(activity.type==exam){ ((Exam)IActivity).DoSomething();}
But this looks acceptable given there is no good alternative, but it really clutters your code.
- From a student perspective, he/she is only interested in the following
-- show me the list of all activities I have to perform, but tell me what type of activities they are
-- Once I attempt/do an activity, he/she expect different behavior as well, for example, Training does not have any grading attached to it, while exam does.
--- Exam is allowed to take only once.
--- Summary Exam grading is different than Full Exam.
--- Summary Exam Allow Late Submission while Exam does not have that feature at all.
Now again in order to call the correct behavior of IActivity, enum is helpful but it is cluttering the code base at all levels, where the decision has to be made. And IActivity does not know about the behavior Exam at all, and exam can be of multiple types, thus adding to the complexity so another enum to see what kind of exam it is since Summary Exam and Full Exam only differs in grading behavior, and everything else is same. Now with this, another switch statement or if/else on all consumer classes.
* Factories will help with this, but I am worried it will become too complex, having different methods in factories, since Exam can be in a valid state (draft) with a different combination of properties.
So the system is interested both in Activity and concrete types i.e. Exam, Training, etc but in different scope.
** Additional complexity, what if the teacher wants to create a new type of activity which is saying "Its Path activity, the exam is only available when the student takes this training." Now, the student is still interested to see a list of all activities, just want to know the type of it (as a label).
Lately, I have been thinking about composition instead of inheritance, where there is only one type, Activity, and it has a set of a feature collection. Each feature contains its own behavior in its own class. Have not done it before, not sure if this sort of approach exists or even beneficial.
Thanks again for the detailed answer again, would love to hear your thoughts.
Or why is the following impossible:
class Material
{
class Keys
{
...
}
Material.Keys Keys { get; set; } // Illegal
}
I don't see any possible ambiguity. When accessed by instance, return the property. When access statically, return the class. Or am I missing something?
I'm not asking for a "fix" (I know I could just name it differently, like MaterialKeys or the like), but more of a technical reason behind this limit.
But imagine you had this:
class Material
{
class Keys
{
...
}
static Material.Keys Keys = new Keys();
}
Now both are at "static" scope. Now, can the compiler disambiguate in all cases? If not, then this can't be allowed.
I suppose it's possible that the disambiguation would work for static fields/properties/methods, and not for instance members. Or the other way around. If that were the case, would you want the language specification to allow an instance member to have the same name as an internal class, but disallow it for statics? That would just be confusing.
But then, having a member match the name of an internal class is pretty confusing anyway.
"Anything that's not ambiguous should be legal" is absolutely NOT a design principle of the C# language. The C# language is designed to be a "pit of quality" language; that is, the rules of the language should throw you into a pit full of clearly correct code, and you have to work to climb out of the pit to turn it into incorrect code. The idea that "whatever is not ambiguous should be legal" works in most cases directly against the concept of a "pit of quality" language.
Furthermore, your idea that I need to provide you a justification for not doing a feature is backwards. We don't ever need to provide justification for not doing a feature. Rather, proposed features must be justified by demonstrating that their benefits outweigh their enormous costs. Features are very expensive and we have a limited budget; we must only do the very best features to yield their benefits to our customers.
Your proposed feature enables the easy production of code that is brittle and confusing; it helps make C# into a "pit of despair" language instead of a "pit of quality" language. Features which add brittleness and confusion to the language must add an enormous benefit to compensate for those costs. What is in your opinion the enormous benefit that this feature adds to the language that justifies its costs?
If the answer is "there is no such benefit" then now you know why the language doesn't have that feature: because it makes the language worse, net.
If there is a benefit, I'm happy to consider its merits for hypothetical future versions of the language.
You said,
When accessed by instance, return the property. When access statically, return the class.
But what if you say just Keys somewhere inside Material? Is this a static or instance access? Does this refer to the property Keys or the nested type Keys? It is actually ambiguous.
For example,
class Material
{
class Keys
{
public static int Length;
}
string Keys { get; set; }
public void Process()
{
// Does this refer to string.Length (via property Keys)
// or Material.Keys.Length? It actually refers to both.
Console.WriteLine(Keys.Length);
}
}
As pointed out in the comments, this is not the whole story; but almost. It is valid to have a property named Color of the type Color and there is no clash:
public Color Color { get; set; }
Color.FromName(...) // refers to static method on the type ‘Color’
Color.ToString() // refers to instance method on the property’s value
But this is easy to resolve simply because things in the current scope win over things in more outer scopes:
public class MyType { public string FromName(string name) { return null; } }
public MyType Color;
Color.FromName(...) // unambiguously refers to MyType::FromName(string)
// via the property Color
Not so easy in your example — the nested class Keys and the property Keys are in the same scope (have the same declaring type). How do you decide which to give priority? And even if you did decide to give one of them priority, this would be only marginally useful because you could still only have two things of the same name, and one would have to be static and the other instance.
My answer approaches the question from a slightly different perspective, compared to the other questions. Of the following two statements in a C# language specification:
The same identifier may not be used in different definitions within one scope
and
The same identifier may not be used in different definitions within one scope, unless it is probably impossible for any ambiguity to arise when the identifier is used
, the first is much simpler.
Simplicity is a key goal in language design, because simpler languages are easier for compiler and interpreter authors to implement, easier for tools to generate and manipulate, easier for beginners to learn, and easier for programmers to understand. When considering any language feature, the complexity that that feature adds to the language should be considered as a negative, and must therefore be balanced by an at least equal measure of usefulness. As you stated yourself, allowing this would add no real functionality (as it is so easy to work around), so there was no compelling reason to further complicate the C# spec by including it.
Because the nested class Keys is a member of Material as is the property Keys. You've got two members called Keys.
In the same way you can't have two properties called the same thing:
public class Bar
{
private bool Foo { get; set; }
private string Foo { get; set; }
}
When you access Foo which one are you trying to access?
public class Material : Keys
{
private Keys K { get; set; }
}
public class Keys
{
}
Works fine, but is probably not what you're after.
I run into this frequently enough that I thought I'd see what others had to say about it.
Using the StyleCop conventions, I find that I often have a property name that is hard to make different than the class name it is accessing. For example:
public class ProjectManager
{
// Stuff here
}
public class OtherClass
{
private ProjectManager ProjectManager { get; set; }
}
It compiles and runs, but seems like it would be an easy way to confuse things, even with the use of "this".
This is actually a very common pattern in .Net programming. Particularly so with enum types and members as it's the .Net Design Guidelines recommended way of programming.
4.0 design guidelines reference
http://msdn.microsoft.com/en-us/library/ms229012(v=VS.100).aspx
While it may be a bit confusing, it's not once you've seen it a few times. The tools well support this pattern and given one is a type and the other an instance it's hard to accidentally invert them without causing a compilation error.
That is a typical naming convention when there will only be a single property of type ProjectManager within any given class. It ceases to be confusing because there are no other uses of the ProjectManager type.
Of course, if there are other uses, then you need different names.
I agree with the other answers. For completeness sake, sometimes I find a way to generalize the class name a bit more. I understand your example was just an example, but one way to do it would be:
public class Person
{
// Stuff here
}
public class OtherClass
{
private Person ProjectManager { get; set; }
}
This helps make it a bit more readable. But it is perfectly acceptable (and even encouraged) to have identical class name and property.
My colleague and I have been having a discussion about what Collections should be called.
For example:
Class Product - Collection - Class Products
or
Class Product - Collection - Class ProductCollection
I've had a look around to see if I can see any guidelines or reasons for using one or the other but nothing seems to spring out. The framework seems to use both variants for example. The argument I can see is that a class that has a collection of products variable should be called Products but it should be of type ProductCollection.
Which is correct if any?
In the same vane is there a standard for the naming of return variable for a function. e.g. retVal?
We mainly code in C#, although I'm not sure that affects my question.
I would say that with generics there should rarely ever be a reason to create a custom collection type. But if you must I would say that ProductCollection would best fit the naming conventions of the framework.
Still, consider using a List<Product> or Collection<Product> or better yet IList<Product> or ICollection<Product>.
Edit: This is in response to MrEdmundo's comments below.
In your case you have two choices. The most obvious choice would be to use inheritance like this:
class Ball { }
class BallCollection : List<Ball>
{
public String Color { get; set; }
public String Material { get; set; }
}
I say obvious because it seems like the best idea at first glance but after a bit of thought it becomes clear that this is not the best choice. What if you or Microsoft creates a new SuperAwesomeList<T> and you want to use that to improve the performance of your BallCollection class? It would be difficult because you are tied to the List<T> class through inheritance and changing the base class would potentially break any code that uses BallCollection as a List<T>.
So what is the better solution? I would recommend that in this case you would be better off to favor composition over inheritance. So what would a composition-based solution look like?
class Ball { }
class BallCollection
{
public String Color { get; set; }
public String Material { get; set; }
public IList<Ball> Balls { get; set; }
}
Notice that I have declared the Balls property to be of type IList<T>. This means that you are free to implement the property using whatever type you wish as long as that type implements IList<T>. This means that you can freely use a SuperAwesomeList<T> at any point which makes this type significantly more scalable and much less painful to maintain.
Products is certainly not correct IMHO. A non-static class name should represent a noun (not plural), because you should be able to say "x is a [classname]".
Obviously, Products doesn't fit in that scheme. ProductCollection does:
Illustration:
var products = new Products(); // products is a Products
var products = new ProductCollection(); // products is a ProductCollection
Which one "sounds right" ?
Another thing about naming collection classes: I usually try to name collection classes in such way that it is clear what kind of collection it is.
For example:
class ProductCollection: can only be enumerated and the Count retrieved (i.e. only implements ICollection interface(s))
class ProductList: a list that can be manipulated using Add(), Insert(), etc. (i.e. implements IList interface(s))
class ProductDictionary: a dictionary of products accessible by some key (i.e. implements IDictionary interface(s))
The last one can be ambiguous if there could be a doubt what the key of the dictionary is, so it's better to specify what the key type is (like ProductDictionaryByString). But to be honest, I rarely name it this way because most of the time the key will be a string anyway.
The .NET Framework frequently uses a "Collection" postfix for its collection types. StringCollection, ObservableCollection, KeyedCollection, etc. So go with ProductCollection.
Noticed nobody answered you on the retVal stuff (Or I could just be getting blind). Although I'm not an expert; on the matter of the retVal issue I'm not 100% sure what you mean by "naming of return variable", but if you mean stuff like this:
public void GetSomething(out object retVal)
{
retVal = ThingFactory.CreateSomething();
}
I would say, no matter what the convention is, don't do it. It's very annoying. Just return the value instead. If you need to return more than one thing, then I would think the method either does more than one thing (which a method shouldn't) or those things should be wrapped up in some sort of logical class that could be returned instead.
If instead by "naming of return variable" you mean stuff like this:
var retVal = ThingFactory.CreateSomething();
Then I would say name the variable according to what it is. What it is going to be used for. If its a list of cars, call it listOfCars, if it's a piece of bread to be eaten later, call it pieceOfBread or pieceOfBreadToBeEatenLater.
Hope that helped and that it wasn't too far off into a field somewhere :p
Thesaurus.com
Look no further. No longer will you mull over pluralized singularity. Just fasten one of these plural-protectors to your object's name:
Jumble
Gob
Trove
Miscellany
Vocab
Load
Agglomeration
Mound
Series
Lexicon
Muster
Glossary
Hoard
Swarm
Group
Cluster
Convoy
Assemblage
Herd
Mob
Batch
Amassment
Pile
Bank
Congregation
Clump
Volume
Set
Reserve
Compilation
Flock
Army
Make it fun.
Consider the following code:
class Program
{
static void Main(string[] args)
{
Department deathStar = new Department { Name = "Death Star" };
Console.WriteLine("The manager of {0} is {1}.", deathStar.Name, deathStar.Manager.FullName);
deathStar.Manager.FirstName = "Lord";
Console.WriteLine("The manager of {0} is {1}.", deathStar.Name, deathStar.Manager.FullName);
Console.ReadLine();
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get
{
return this.FirstName + " " + this.LastName;
}
}
}
public class Department
{
public string Name { get; set; }
public Person Manager { get; private set; }
public Department()
{
this.Manager = new Person { FirstName = "Darth", LastName = "Vader" };
}
}
which produces the following output:
The manager of Death Star is Darth Vader.
The manager of Death Star is Lord Vader.
Even though I can't change Manager to be a different or new instance of Person (private set accessor), I can change it's properties (which have public set accessors).
So, is assigning a value to a property through a set accessor via its container's get accessor a bad thing? In other words, is this a code smell?
EDIT:
This is just a sample to illustrate a point. Person and Department were created for this sample only.
Not necessarrily.
For example, look at the parameters collection on a SqlCommand object. You can change the items in the collection, but you can't assign a new parameters collection to the command object.
Take your example, if you had a UI maintaining Person objects, and you needed to change a persons first name, it's perfectly valid to change the persons first name, leave the last name and PersonId fields alone, then update a database table using the PersonId field.
It all sounds OK to me
Yes, this is a code smell.
While this seems like a fairly harmless practice, public properties expose the fields of your class to arbitrary change and create needless dependence on implementation details. You may as well be using a struct. (I'm not implying that structs are bad either. Procedural programming is just as useful as OOP. It all depends on the problem being solved) The point of encapsulation is to hide implementation details from the class' dependents. Rather you should expose abstract interfaces that allow dependent classes to modify the internal data without needing to know its implementation. Consider the following examples:
public interface Vehicle {
double FuelTankCapacityInGallons{get;}
double GallonsOfGasoline{get;}
}
public interface Vehicle {
double getPercentFuelRemaining();
}
Both interfaces will get you the amount of remaining gasoline. The first through concrete terms, the second through abstraction. If the size of the tank changes or you need to implement a European car the first example would require changes to both the Vehicle and whatever class is using it. While the second would only require changes to the Vehicle implementation.
The example I used is from the book Clean Code - A Handbook of Agile Software Craftsmanship by Robert C. Martin.
I would also look up Law of Demeter.
I'd say that the line:
deathStar.Manager.FirstName = "Lord";
is perfectly clear in its intent, so it doesn't bother me.
What does bother me is the private set on Manager.
This means that once a department is created, it's manager can never be changed.
As a model for reality, this is a big time smell.
Is it "a bad thing"? Not intrinsically. Is it a sign that you should re-examine your design of the classes? Yes. Why is something that creates a Department modifying a Person object? Should you be implementing a ChangeManager method on Department instead? Maybe, maybe not. But it's a question worth asking.
It's not a problem as long as Person is not a struct : if it is, then the Manager property will return a copy of the Person, and you will be setting the FirstName property on that copy, not on the department's Manager. But anyway, the compiler would scream if you tried to do that...
It's a question of OOP purity.
Not all pieces of code should be pure OOP. It's a matter of project complexity, number of programmers involved, maintainability, etc.
Your example is very simple, and that's why you can read so many opinions
It is sometimes hard to illustrate the advantages of OOP with simple examples.
Anyway, my thoughts:
It smells.
The line of code that really bothers me is
deathStar.Manager.FirstName = "Lord";
It can easily change to something like
deathStar.Manager.Address.City.Name = "Paris"
So in one line of code you see 4 classes in use! This makes a very strong assumption that the coupling of all 4 classes remains the same. In other words, it keeps the classes highly coupled.
You can resolve this by working with interfaces rather than concrete classes, and you can adopt the "Tell don't ask" guideline (Yahoo search; yes, Yahoo).
Here's a nice PDF that discusses OOP and refactoring (in Java, but the ideas are understood easily), see "Transitive coupling" section.
I think this is one of the reasons people tout functional languages so much - no "side effects". I don't think there is anything technically wrong with this, but it can make maintenance very difficult. To paraphrase Jurrasic Park, "...just because you can do something, doesn't mean you should!"