We are almost at the finish line with our current example. ๐โโ๏ธ There are just a few more things to sort out, so letโs connect the remaining dots and perform some improvements!
Now is the time to reflect back on our intentions: writing quality code. Here we are going to review the SOLID principles and assess the quality of our code.
Let's go! ๐
SOLID. check
Single responsibility principle
Reminder: A code entity should have single responsibility.
Let's use our data model as an example. We could create a monster like this:
class MediaMonster {
var id: Int
var title: String
var artistName: String
var artworkUrl: String
var collection: String?
var sourceUrl: String
var artworkData: Data?
var swagId: Int
var swagTitle: String
var swagArtworkUrl: String
var swagSourceUrl: String
var swagArtworkData: Data?
init(/* all the necessary variations */) {
// ...
}
func loadMediaArtwork() {
// ...
}
func loadSwagArtwork() {
// ...
}
}
On top of that, we could use the prefix media
for all the media-related properties. ๐ฑ
Does this look overwhelming?
Instead, we have three clean classes to hold data and let the service entity handle the image loading:
class MediaBrief {
var id: Int
var title: String
var artistName: String
var artworkUrl: String
var artworkData: Data?
init(...) {
// ...
}
}
class Media: MediaBrief {
var collection: String?
var sourceUrl: String
init(...) {
// ...
}
}
class Swag {
var id: Int
var title: String
var artworkUrl: String
var sourceUrl: String
var artworkData: Data?
init(...) {
// ...
}
}
class MediaService {
// ...
static func getImage(...) {
// ...
}
// ...
}
It's ok to create slightly imperfect entities. However, always make time for refactoring and aim for the best you can do at the time!
Open/closed principle
Reminder: Code entities should be open for extension and closed for modification.
Any violations of this kind in our code?
Ok, I'll give you a hint...
We are all good here!
Instead, go ahead and identify some good examples where this principle is being followed!
Your turn! This time you are on a hunt for goodies!

Let me know what you found!
Extensions maybe?
Liskov substitution principle
Reminder: A subclass should be usable in the context of its superclass.
This one is interesting!
Try to identify the code in our project that violates this principle!

OK...
Time to share your findings!
(I haven't found any!)
Interface segregation principle
Reminder: The interface should implement only necessary capabilities for the context.
Thankfully, overall we don't have such faults in our code. A monster example we've come up with in the beginning of this chapter could serve as a good example. We would be passing around the entire object with all of the properties that wouldn't be needed at times. We wouldn't need extra media data for the list view or any of the swag functionality at all!
Good thing we don't have that problem! ๐
Dependency inversion principle
Reminder: A code entity should depend on the least number of other entities.
A good example to analyze this principle is the MediaService class. Our small project is used as a model to explore essential networking capabilities. However, along the way we've built a number of traps for ourselves. The same class is responsible for:
Dealing with the particulars of media object
Performing networking
Parsing all the data
Fetching images
In larger projects, typical configuration would have separate classes that are responsible for:
Networking - only sending and receiving data.
Creating requests based on abstract parameters.
Object-specific communication (we've started here and incorporated the rest).
Fetching media and images, for example, would be at the same level - nothing as a subitem of another.
Parsing data - object specific.
Think about how it can be improved - it's all in your capable hands! ๐
The coding attitude
Imagine your code will live forever, or at least a century from now. ๐ Itโs not out of the question considering some code written in old programming languages is still functioning and even serves as a basis for new software. And, Swift is a very new language that quickly gained in popularity which is a good sign itโs not going anywhere in the near future. Itโs also a sign that it will keep changing and evolving, which gives us a reason to write good code that will allow for quick adjustments and easy migrations to newer versions.
Aim to deliver the best you can for the moment! ๐ช
Let's recap!
[S] - Keep your code elements at minimal and straight-to-the-point functionality - ideally, single responsibility.
[O] - Keep parts of code entities closed for modification and open for extension.
[L] - Ensure subclasses keep the superclass functionality intact.
[I] - Provide only useful interface in the context of a particular application.
[D] - Make your code entities the least dependent possible on other entities.
Always perform the SOLID check!
Moving forward
Congratulations on fantastic progress! In this course, weโve worked with new aspects of an application - learned to work with collection views and practiced networking! You also now know how to handle app requirements that may come in different forms and shapes. Those will definitely become valuable additions to your development equipment.
Knowing the basics is a necessary starting point to continue exploring those concepts and elements in depth, as well as expand your knowledge!
Keep learning! ๐คฉ