Question

Writing a User object in Swift, though my question relates to any strongly typed language. A User can have a bunch of links (FacebookProfile, InstagramProfile, etc). A few questions around this.

  1. Is it good practice to wrap links in their own object?
    struct User {
       var firstName: string
       var lastName: string
       var email: string
       var links: Links
    }
    struct Links {
       var facebook: string
       var instagram: string
       var twitter: string 
    }

Or should they be loose? I know technically both ways are fine, but wondering if there is a recommended approach, in general--especially for readability.

struct User { 
   var firstName: string
   var lastName: string
   var email: string
   var facebookLink: string
   var twitterLink: string
   var instagramLink: string
}
  1. In a scenario like this, should links be a collection/list? I figured it should not be a list because there is a fixed number of link options available, and not a growing number. Is my thinking right?

  2. Is it good practice to place my networking methods inside the User object, like getUsers, getUser, updateUser?

I know these could be subjective, but I am trying to understand what the best practice around similar situations is. Would appreciate any pointers.

Was it helpful?

Solution

You will either need

  • zero of a thing,
  • one of a thing, or
  • an arbitrary number of the thing.

I'm shocked that your design predicts that the number of needed links will always be three and that you know what their names are forever.

What I'm preaching is called the zero one infinity rule. It might not be obvious at first but it's what tells me your design is not future tolerant.

I'd feel differently if there was something about these links that was special to them. Some special thing that I do different when accessing a facebook link that I don't do for a twitter link. That would make them different things. But that isn't indicated in this code.

That's why I'm not bothered by the email string. I know that is used in a different way then the links.

So until I see a reason to use these links differently I'm on the side of a link collection.

OTHER TIPS

You are on the verge of falling into the "I see a technical possibility" trap.

Just because you see a common trait among items does not mean it makes sense to apply some aggregation on them. The aggregation should mean something. Not on a technical level but in your problem domain.

They are all links alright, but in the context of a user class, does that mean anything? No. It is just as meaningless as it would be to sub-group using classes named "strings" and "numbers".

The trouble with this kind of thing is it blurs your model. It forces the code reader to sever the meaningful from the meaningless, before having a full understanding of the domain.

No one ever talks about a user's links. It would be different if you would call your aggregation SocialNetworkIds. Because that would actually mean something, it would be a true property of User rather than an arbitrary technical collection.

In general, I think it would be reasonable to have the links be in their own struct if you are likely to apply similar operations to each of them, and particularly if you always perform the same operations on all of them. If they are for unrelated purposes in your application, then I would make them separate. For example, if they were the user's homepage, their health insurance provider's web site, and a link to their favorite news site, I probably wouldn't group them together as they seem unrelated. But for 3 social media sites, it seems like they will be treated similarly in an app, and as such should probably be grouped together. I would use a more descriptive name than Links though. (What type of links? For what purpose in your app?)

I agree with your thinking on #2. As mentioned above, if the number were to grow or become variable, a list or other collection would be a good choice, but not for the scenario you've described.

I would not place networking methods inside the objects that hold the data retrieved by the network. Where the data came from, and how to obtain it are usually irrelevant to the main purpose of a class. What if in the future you want to get some data from disk? Or want the user to enter it? Go far enough down that road and a simple User class has to have code to handle every possible method of data entry and retrieval. Just make a User class hold and maintain the data while it's in memory. Everything else can be handled by more appropriate classes.

Licensed under: CC-BY-SA with attribution
scroll top