I've few methods which acept collections of fixed size (e.g. 2, 3, 5). And I can't decide which way is better:
public void Foo(IEnumerable<Object> objects)
{
if(objects.Count() != 3)
{
throw new Exception()
}
// actions
}
public void Foo(Object objectA, Object objectB, Object objectC)
{
// actions
}
Is there any ultimate +\- of each option?
The second is much better in my view:
It's obvious from the signature that it's expecting 3 values
Failures are flagged at compile time instead of execution time
If you have a specific number of members that are required, use your second option. It is confusing to the consumer of your method if a collection is allowed but then an exception is thrown at run time. This may or may not be caught if proper testing is not utilized and it is misleading. Always design for the person who will consume your code, never assuming that you will always be the one to maintain it.
I would go for this:
public class Bar
{
public Object object1;
public Object object2;
public Object object3;
// add a constructor if you want
}
...
public void Foo(Bar b)
{
// actions
}
Related
This is a question about design/best practices.
I have the following class:
class MyClass
{
public bool IsNextAvailablle()
{
// implementation
}
public SomeObject GetNext()
{
return nextObject;
}
}
I consider this a bad design because the users of this class need to be aware that they need to call IsNextAvailable() before calling GetNext().
However, this "hidden contract" is the only thing which I can see wrong about, that the user can call GetNext() when there is nothing avaiable. (I would be happy if anyone can point out other scenarios in which this implementation is bad)
A second implementation I thought of is that GetNext() throws an exception if nextObject is not available. Client will have to handle the exception, plus it can have a small impact on performance and cpu usage due to the exception handling mechanism in .net (I expect this exception to be thrown quite often). Is the exception-driven way a better approach than the previous one? Which is the best way?
That's just fine. In fact, this two-step process is a common idiom for a bunch of .NET BCL classes. See, for example, an IEnumerable:
using(var enumerator = enumerable.Enumerator())
{
while(enumerator.MoveNext())
{
// Do stuff with enumerator.Current
}
}
Or DbDataReader:
using(var dbDataReader = dbCommand.ExecuteReader())
{
while(dbDataReader.Read())
{
// Do stuff with dbDataReader
}
}
Or Stream, for that matter:
var buffer = new byte[1024];
using(var stream = GetStream())
{
var read = 0;
while((read = stream.Read(buffer, 0, buffer.Length)))
{
// Do stuff with buffer
}
}
Now, your entire IsNextAvailable()/GetNext() could very well be replaced by implementing an IEnumerable<SomeObject> and thusly your API will be immediately familiar to any .NET developer.
Neither of them is an ideal solution, where the Exception has my personal preference because it allows a single point of entry.
You could opt to implement the IEnumerable<SomeObject> interface. In that way you can provide an enumerator that actually does all the checking for you.
class MyClass : IEnumerable<SomeObject>
{
private bool IsNextAvailablle()
{
// implementation
}
private SomeObject GetNext()
{
return nextObject;
}
public IEnumerator<SomeObject> GetEnumerator()
{
while (IsNextAvailablle())
{
yield return GetNext();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Disclaimer: This question is in hindsight asking for opinions so I'm torn between closing it (and deleting my answer) or leaving my answer here.
In any case, this is my opinion, and only my opinion.
You should always strive for "pit of success".
The "pit of success" is best described by Jeff Atwood: Falling into the Pit of Success:
The Pit of Success: in stark contrast to a summit, a peak, or a journey across a desert to find victory through many trials and surprises, we want our customers to simply fall into winning practices by using our platform and frameworks. To the extent that we make it easy to get into trouble we fail.
The term was coined by Rico Mariani but I am unable to find a clear source for this term.
Basically, make an API that invites correct use and makes it hard to use wrong.
Or let me rephrase that: Make the correct usage of your API the only way to use your API.
In your case, you haven't done that.
Broad Explanation
In the case of "is it bad design to require consumers of my API to call methods in the right order, otherwise bad/incorrect things will happen?" - the answer is yes. This is bad.
Instead you should try to restructure your API so that the consumer "falls into the pit of success". In other words, make the API behave in the way that the consumer would assume it would by default.
The problem with this is that it invariably falls down to what people considers "by default". Different people might be used to different behavior.
For instance, let's say we get rid of IsNextAvailablle [sic] altogether and make GetNext return null in the case of no next available.
Some purists might say that then perhaps the method should be called TryGetNext. It may "fail" to produce a next item.
So here's your revised class:
class MyClass
{
public SomeObject TryGetNext()
{
return nextObject; // or null if none is available
}
}
There should no longer be any doubts as to what this method does. It attempts to get the next object from "something". It may fail, but you should also document that in the case where it fails, the consumer get null in return.
An example API in the .NET framework that behaves like this is the TextReader.ReadLine method:
Return Value:
The next line from the reader, or null if all characters have been read.
HOWEVER, if the question "is there anything else" can easily be answered, but "give me the next something" is an expensive operation then perhaps this is the wrong approach. For instance, if the output of GetNext is an expensive and large data structure that can be produced if one has an index into something, and the IsNextAvailablle can be answered by simply looking at the index and seeing that it is still less than 10, then perhaps this should be rethought.
Additionally, this type of "simplification" may not always be possible. For instance, the Stopwatch class requires the consumer to start the stopwatch before reading time elapsed.
A better restructuring of such a class would be that you either have a stopped stopwatch or a started stopwatch. A started stopwatch cannot be started. Let me show this class:
public class StoppedStopwatch
{
public RunningStopwatch Start()
{
return new RunningStopwatch(...);
}
}
public class RunningStopwatch
{
public PausedStopwatch Pause()
{
return new PausedStopwatch(...);
}
public TimeSpan Elapsed { get; }
}
public class PausedStopwatch
{
public RunningStopwatch Unpause()
{
return new RunningStopwatch(...);
}
public TimeSpan Elapsed { get; }
}
This API doesn't even allow you to do the wrong things. You cannot stop a stopped stopwatch and since it has never been started you can't even read the time elapsed.
A running stopwatch however can be paused, or you can read the elapsed time. If you pause it, you can unpause it to get it running again, or you can read the elapsed time (as of when you paused it).
This API invites correct usage because it doesn't make incorrect usage available.
So in the broad sense, your class is bad design (in my opinion).
Try to restructure the API so that the correct way to use it is the only way to use it.
Specific Case
Now, let's deal with your specific code example. Is that bad design, and how do you improve it?
Well, as I said in a comment, if you squint slightly and replace some of the names in the class you have reimplemented IEnumerable:
class MyClass interface IEnumerable
{ {
public bool IsNextAvailablle() public bool MoveNext()
{ {
// implementation
} }
public SomeObject GetNext() public SomeObject Current
{ {
return nextObject; get { ... }
} }
} }
So your example class looks a lot like a collection. I can start enumerating over it, I can move to the next item, one item at a time, and at some point I reach the end.
In this case I would simply say "don't reinvent the wheel". Implement IEnumerable because as a consumer of your class, this is what I would you expect you to do.
So your class should look like this:
class MyClass : IEnumerable<SomeObject>
{
public IEnumerator<SomeObject> GetEnumerator()
{
while (... is next available ...)
yield return ... get next ...;
}
public IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
Again, this is "pit of success". If the class is in reality a collection of things, use the tools built into .NET to make it behave like any other .NET collection.
If you were to document your class as "a collection of SomeObject instances" I would grab my LINQ and foreach toolkit by default. When I get a compiler error I would start looking at the members to find the actual collection because I have a very strong sense of what a collection should be in .NET. I would be very puzzled if you reimplemented all the tools that would be able to handle IEnumerable but simply didn't make it implement this interface.
So, instead of me having to write code like this:
var c = new MyClass();
while (c.IsNextAvailablle())
{
var item = c.GetNext();
// process item
}
I can write this:
var c = new MyClass();
foreach (var item in c)
// process item
Why should the users even have to call IsNextAvailable? By rights, IsNextAvailable should be private and GetNext should be the one calling it, and then throw an exception or a warning or return a null if there is nothing available.
public SomeObject GetNext()
{
if(IsNextAvailable())
return nextObject;
else
throw new Exception("there is no next"); // this is just illustrative. By rights exceptions shouldn't be used for this scenario
}
private bool IsNextAvailable()
{
// implementation
}
I have a class:
public class MyClass: IMyInterface
{
int _parameter;
public Myclass(int parameter)
{
_parameter = parameter;
//Do other things
}
public int FrequentlyCalledFunction()
{
if(_parameter == 0)
{
return 0;
}
else
{
int result;
//Do some calculations
return result;
}
}
}
Since the _parameter is assigned once in the constructor, entering the if statement every time the FrequentlyCalledFunction is called seems somewhat inefficient for an already created instance .
Thus, I thought to modify the code as follows. Declare a delegate
public delegate int MyDlg();
public class MyClass: IMyInterface
{
int _parameter;
MyDlg _intermediate;
public Myclass(int parameter)
{
_parameter = parameter;
_intermediate = _parameter == 0 ? _returnZero : _calculateAndReturn;
//Do other things
}
public int FrequentlyCalledFunction()
{
return _intermediate();
}
int _returnZero()
{
return 0;
}
int _calculateAndReturn()
{
int result;
//Do some calculations
return result;
}
}
So now, the check will be performed only once at the moment of creating the instance. On the other hand the if statement is replaced with an additional delegate call.
The question is, assuming that the performance is very important, which approach is better?
P.S.
The FrequentlyCalledFunction is a method from the interface IMyInterface, thus, I cannot define a MyDlg FrequentlyCalledFunction and call it from the outside of the class.
You are thinking about it too much. The best way to improve performance in this case is to make MyClass abstract, and to define two subclasses: MyClassWithCalculations and MyClassWithoutCalculations.
When you are about to create an instance of MyClass, check the parameter: if it is zero, instantiate MyClassWithoutCalculations. If it is non-zero, instantiate MyClassWithCalculations. No delegates, no ifs, no convoluted stuff.
That having been said, let me also add that you are probably wrong in thinking that an innocent if( variable == 0 ) statement can affect performance in any significant way whatsoever.
I came across this question trying whilst searching for ideas to improve the performance in an existing app. The scenario:
Stream of updates that arrive at a rate of 44 Hz (every ~23ms)
Updates are only 16 bytes of data
What happens to the update (how it should be transformed before being output to a consuming system) depends on the value of a Guid.
That Guid...
Changes relatively infrequently -- not for 8 hours, then a couple of times over 10 minutes.
Changes as a result of a call from a separate system.
The objective was to reduce the time between receiving an update and posting a value out to a consuming system.
In my scenario, an if statement checking the Guid on every update vs a delegate being used to point to another function had cost of 4ms. For us, it was worth swapping out as all our other optimisations were sub 1ms.
I guess the real answer is "test, test, test", but I thought I'd share my experience.
This has a game development project under itself, but it's really about coding and mapping data to other pieces of data. This is why I decided to post it here.
The format that I'm using for external inventory item data storage:
[ID:IT_FO_TROUT]
[Name:Trout]
[Description:A raw trout.]
[Value:10]
[3DModel:null]
[InventoryIcon:trout]
[Tag:Consumable]
[Tag:Food]
[Tag:Stackable]
[OnConsume:RestoreHealth(15)]
[OnConsume:RestoreFatigue(15)]
The question is concentrated upon the last 2 OnConsume properties. Basically, the two properties mean that when the item gets consumed, the consumer's health goes up by 15 points, and his fatigue does so as well. This, in the background, invokes 2 different methods:
void RestoreHealth(Character Subject, int Amount);
void RestoreFatigue(Character Subject, int Amount);
How would you go about mapping the methods to their in-file string counterparts? This is what I thought of:
Every time an item gets consumed, a list of strings (the events) gets passed to an Item event manager. The manager parses each string and calls the appropriate methods. Very easy to set up, and since this is not an operation that happens too often, the impact on performance might not be considerable (strings will also be tiny (max 10-15 characters) in size, and parsed in O(n) time).
Each inventory item (class) parses the string events once and only once, on initialization. Each string event gets mapped to its appropriate method via a dictionary. This is the most efficient method in terms of performance that I can think of, but it makes it extremely difficult to do other things:
All of the values in the dictionary would have to be delegates of the same kind. This means I cannot keep
a) RestoreHealth(int)
b) SummonMonster(Position, Count)
in the same dictionary, and would have to set a new data structure for each kind of callable method. This is a tremendous amount of work to do.
Some ways that came to mind, to improve both methods:
I could use some sort of temporary cache inside the Item event
manager, so that an item's OnConsume events don't get parsed
twice? I might hit the same issues as the ones I hit during 2)
though, as the cache would have to be a map<InventoryItem,List<delegate>>.
The hashtable data structure inside the .NET libraries allows
for any kind of object to be a key and/or value at any given time
(unlike the dictionary). I could use this and map string A to
delegate X, while also having mapped string B to delegate Y
inside the same structure. Any reasons why I should not do this? Can
you foresee any trouble that would be brought by this method?
I was also thinking about something in the ways of reflection, but I'm not exactly experienced when it comes to it. And I'm pretty sure parsing the string every time is faster.
EDIT
My final solution, with Alexey Raga's answer in mind. Using interfaces for each kind of event.
public interface IConsumeEvent
{
void ApplyConsumeEffects(BaseCharacter Consumer);
}
Sample implementer (particular event):
public class RestoreHealthEvent : IConsumeEvent
{
private int Amount = Amount;
public RestoreHealthEvent(int Amount)
{
this.Amount = Amount;
}
public void ApplyConsumeEffects(BaseCharacter Consumer)
{
Consumer.Stats.AlterStat(CharacterStats.CharStat.Health, Amount);
}
}
Inside the parser (the only place where we care about the event's particularities - because we're parsing the data files themselves):
RestoreHealthEvent ResHealthEv = new RestoreHealthEvent (Value);
NewItem.ConsumeEvents.Add (ResHealthEv );
When a character consumes an item:
foreach (IConsumeEvent ConsumeEvent in Item.ConsumeEvents)
{
//We're inside a parent method that's inside a parent BaseCharacter class; we're consuming an item right now.
ConsumeEvent.ApplyConsumeEffects(this);
}
Why not "map" them to "command" classes once-and-only-once instead?
For example,
[OnConsume:RestoreHealth(15)]
[OnConsume:RestoreFatigue(15)]
could be mapped to RestoreHealth and RestoreFatigue command classes that can be defined as:
public sealed class RestoreHealth : ICommand {
public int Value { get; set; }
//whatever else you need
}
public sealed class SummonMonster : ICommand {
public int Count {get; set; }
public Position Position { get; set; }
}
Consider commands as just wrappers for your parameters at this point ;) So instead of passing multiple parameters you always wrap them and pass only one.
It also gives a bit of semantics too.
Now you can map your inventory items to commands that need to be "sent" when each item is consumed.
You can implement a simple "bus" interface like:
public interface IBus {
void Send(ICommand command);
void Subscribe(object subscriber);
}
and now you just get an instance of IBus and call its Send method when appropriate.
By doing this you separate your "definition" (what needs to be done) and your logic (how to perform an action) concerns.
For the receiving and reacting part you implement the Subscribe method to interrogate the subscriber instance (again, once and only once) figuring out all its method which can "handle" commands.
You can come up with some IHandle<T> where T: ICommand interface in your handlers, or just find them by convention (any Handle method that accepts only one argument of ICommand and returns void), or whatever works for you.
It is basically the same part of "delegate/action" lists that you were talking about except that now it is per command:
map<CommandType, List<action>>
Because all the actions now accept only one parameter (which is ICommand) you can easily keep them all in the same list.
When some command is received, your IBus implementation just gets the list of actions for the given command type and simply calls these actions passing the given command as a parameter.
Hope it helps.
Advanced: you can do one step further: have a ConsumeItem command:
public sealed void ConsumeItem: ICommand {
public InventoryItem Item { get; set; }
}
You already have a class that is responsible for holding a map between InventoryItem and Commands, so this class can become a process manager:
It subscribes to ConsumeItem command (through the bus)
In its Handle method it gets the list of commands for the given inventory item
It sends these commands to the bus.
Well, now we have separated clearly these three concerns:
While consuming an inventory item we just "know" about IBus and send a ConsumeItem command and we don't care what happens next.
The "ConsumeInventoryManager" (whatever you call it) also knows about IBus', subscribes forConsumeItem` command and "knows" what needs to be done when each item is consumed (list of commands). It just sends these commands and doesn't care who and how handle them.
The business logic (characters, monsters, etc) just handle the commands that make sense to them (RestoreHealth, Die, etc) and don't care where (and why) they came from.
Good luck :)
My advice is to use reflection, that is define a method that invokes the desired method based on the specified name. Here's a working example:
class Program
{
static void Main(string[] args)
{
SomeClass someInstance = new SomeClass();
string name = Console.ReadLine();
someInstance.Call("SayHello", name);
}
}
class SomeClass
{
public void SayHello(string name)
{
Console.WriteLine(String.Format("Hello, {0}!", name));
}
public void Call(string methodName, params object[] args)
{
this.GetType().GetMethod(methodName).Invoke(this, args);
}
}
You can do it this way provided the following conditions hold:
You are absolutely sure that a call is possible, that is a method of the specified name exists and the number and types of parameters are correct
The method of the specified name is not overloaded, otherwise You'll get a System.Reflection.AmbiguousMatchException
There exists a superclass from which all of the classes You want to use the Call method on derive; You should define this method in that class
To assure* that conditions 1. and 2. are satisfied You could use a more specific version of Type.GetMethod which takes into account not only the name of the method, but also the number and types of the parameters, and check that there is such a method before invoking it; then the Call method would look like this (*it won't work for methods with parameters marked as out or ref):
public void Call(string methodName, params object[] args)
{
//get the method with the specified name and parameter list
Type[] argTypes = args.Select(arg => arg.GetType()).ToArray();
MethodInfo method = this.GetType().GetMethod(methodName, argTypes);
//check if the method exists and invoke it
if (method != null)
method.Invoke(this, args);
}
REMARK: MethodInfo.Invoke method actually returns an object, so You could define the Call method to return some value by specifying the return type and using the return keyword together with an appropriate cast or some other method of converting the result to the desired type, if it's possible - remember to check if it is.
If condition 3. isn't satisfied, I'd go with writing an extension method. Here's an example of an extension method that returns a generic value, which I think should be sufficient in most cases (again, it won't work with ref or out) and should work on almost every object possible in the .NET Framework (I'd be grateful for pointing out a counterexample):
public static class Extensions
{
//invoke a method with the specified name and parameter list
// and return a result of type T
public static T Call<T>(this object subject, string methodName, params object[] args)
{
//get the method with the specified name and parameter list
Type[] argTypes = args.Select(arg => arg.GetType()).ToArray();
MethodInfo method = subject.GetType().GetMethod(methodName, argTypes);
//check if the method exists
if (method == null)
return default(T); //or throw an exception
//invoke the method and get the result
object result = method.Invoke(subject, args);
//check if something was returned
if (result == null)
return default(T); //or throw an exception
//check if the result is of the expected type (or derives from it)
if (result.GetType().Equals(typeof(T)) || result.GetType().IsSubclassOf(typeof(T)))
return (T)result;
else
return default(T); //or throw an exception
}
//invoke a void method more conveniently
public static void Call(this object subject, string methodName, params object[] args)
{
//invoke Call<object> method and ignore the result
subject.Call<object>(methodName, args);
}
}
You should then be able to use, for example, someObject.Call<string>("ToString") instead of someObject.ToString(). Finally, at this point I'd strongly recommend:
Use more specific type than object if possible
Use some more sophisticated and unique name than Call - it may get obscured in case some class has a method with the same signature defined
Lookup covariance and contravariance to get more useful knowledge
Could you help me please.
I have one idea but don't know how can I implement it.
So the question is:
Can we interrupt creating an object in constructor
i.e.
//Code
SomeClass someClass = new SomeClass(someCriteria);
So if someCriteria doesn't answer on our requirements we shouldn't create an object and should return null, instead of new object.
Is it possible to implement it in C#?
Best way is a factory class but if your class is so small you can use this:
class SomeClass
{
private string _someCriteria;
private SomeClass(string someCriteria)
{
_someCriteria = someCriteria;
}
public static SomeClass CreateInstance(string someCriteria)
{
if (someCriteria.Length > 2)
{
return new SomeClass(someCriteria);
}
return null;
}
}
class Program
{
static void Main(string[] args)
{
// returns null
SomeClass someClass = SomeClass.CreateInstance("t");
// returns object
SomeClass someClass2 = SomeClass.CreateInstance("test");
}
}
You may want to use a factory class that creates instances of SomeClass returning null if the someCriteria is invalid.
It is quite usual that you check the constructor parameters if they are valid. If not, you usually throw an exception.
I also read a nice advice to provide static methods for validating constructor parameters. This enables the user of your class to check if whatever he is going to pass in the constructor will succeed or not. Those who are certain the parameters are ok (they made some sort of their validation) will go directly with the constructor.
Also consider what the user of your class will possibly do with null instead of the object (if some sort of factory class was used). Would this typically result in an NullPointerException on the next line? It's usually good idea to stop the wrong things as soon as possible, in this case throw the exception and finish. It is cleaner solution than returning null and if someone really wants to (this definetly won't be best practise) he can still catch this exception ...
If the parameters to your constructor are invalid, consider throwing ArgumentException or one of its descendant classes (e.g. ArgumentOutOfRangeException).
The new construct guarantees that an object will be returned (or an exception thrown). So as bleeeah recommended, a factory or similar concept will allow you to apply your logic.
That would be possible. Another way would be to put your checking in before you create the object. Like so
SomeClass someClass = null;
if (someCriteria == VALID)
{
someClass = new SomeClass(someCriteria);
}
Hope this helps.
No it is not possible directly.
You could throw an exception and add the required code to check for the exception and assign null to you variable.
A better solution would be to use a Factory that would return null if some condition fail.
var someClass = SomeClassFactory.Create(someCriteria);
if(someClass != null)
{
}
What is the correct exception to throw in the following instance?
If, for example, I have a class: Album with a collection of Songs:
List<Song>
And a method within Album to add a Song:
public void AddSong(Song song)
{
songs.Add(song);
}
Should I throw an exception if a user attempts to add a song that already exists? If so, what type of exception?
I have heard the phrase: "Only use exceptions in exceptional circumstances", but I want to tell the client implementing Album exactly what has gone wrong (not just return a Boolean value).
In exactly the same situation, the .NET designers at Microsoft chose to throw ArgumentException with a descriptive message. Oh, and they were pretty consistent about that.
If your use case implies that items in the collection should be unique, then you should use a datastructure that enforces that.
By doing that, you not only avoid having to write a O(N) lookup method to check for duplicates, but you can also bubble up the pre-existing duplicate key exception that a collection of this sort would throw.
However, .NET does not have a distinct collection that preserves sort order, though it is very easy to extend List to support this.
The approach I used below sacrifices memory footprint for speed, by storing the unique values in a second HashSet. If memory size was more important, you'd just have to do a O(N) check on each Add operation. Because methods are not virtual (for some reason) in List, I resulted to hiding the base methods using the new keyword.
Note that this is just an example, and is not thread safe, and should probably not be used in a real production application.
public class UniqueList<T> : List<T>
{
private HashSet<T> _internalHash = new HashSet<T>();
public UniqueList() : base() { }
public UniqueList(IEnumerable<T> collection) : base(collection) { }
public UniqueList(int capacity) : base(capacity) { }
public new void Add(T item)
{
if (!_internalHash.Add(item))
throw new ArgumentException("Item already exists in UniqueList");
base.Add(item);
}
public new void AddRange(IEnumerable<T> collection)
{
foreach (T t in collection)
{
this.Add(t);
}
}
public new bool Remove(T item)
{
_internalHash.Remove(item);
return base.Remove(item);
}
public new int RemoveAll(Predicate<T> match)
{
int removedElems = 0;
foreach (T item in this)
{
if (match(item))
{
this.Remove(item);
removedElems++;
}
}
return removedElems;
}
public new void RemoveAt(int index)
{
this.Remove(this[index]);
}
public new void RemoveRange(int index, int count)
{
for (int i = index; i < count; i++)
{
this.Remove(this[i]);
}
}
}
Instead of throwing an exception you could have the AddSong method return a boolean - true if the song is successfully added and false otherwise. Personally, I think throwing an exception would be acceptable in this case if it's reasonable to expect that the song is unique in the collection. For an example, if the collection is a list of songs on an album you don't reasonable expect a duplicate song (same title, same duration, same position in the sequence of tracks, etc.). You have the option of creating your own exception class derived from System.Exception to create custom errors if you want so you could throw an exception that explains exactly why the error occurred.
You can always create your own exceptions. Simply create a class that inherits from Exception(or, in this case, ArgumentException).
Something along the lines of DuplicateItemException (or DuplicateSongException if you want something very specific) sounds about right.
If you want to offer up useful exceptions you may want to have a base exception.
AlbumException
Then taking from CMerat's answer create.
DuplicateSongException
This should of course inherit from AlbumException.
Personally, I would make the Album class immutable. In that case this whole situation would disappear.