0
\$\begingroup\$

I was working in a class, but there are a lot of things that I'm not sure if they're a good practice or not. For example, the => instead of the { }. When should I use it? Also, I'm not pretty sure about the keywords const and readonly. For example, uriImage and key it's something that won't change. So, I assume it'll be const. Nevertheless, summonerName or currentVersion despite they won't change, they will be initialized later. That's why I assumed they should be readonly.

Another thing that I was wondering is the Key Api. What'd be the correct way of using a Key api? They could do reversing to the program and take the keyApi?

All good practice tips, and so on, are welcome, thank you very much in advance.

class GameApi
{

   private const    string uriImage = "http://opgg-static.akamaized.net/images/lol/champion/";
   private const    string key = "XXX-XXXXX-XXXXXXXX-XXXXXX-XXXXXX";
   private readonly string summonerName;
   private readonly string currentVersion;
        
   private ChampionListStatic championList;
   private Summoner summonerObject;
   private RiotApi  api;
    
   public GameApi(string _summonerName)
   {
       api = RiotApi.GetDevelopmentInstance(key);
       summonerName = _summonerName;

      try
      {
         // gets currentVersion so I can work with the GetAllAsync() method.
         // Save all champions in championList to work with it in the GetImageUri method.

         currentVersion = api.DataDragon.Versions.GetAllAsync().Result.First();
         summonerObject = api.Summoner.GetSummonerByNameAsync(RiotSharp.Misc.Region.Euw, _summonerName).Result;
         championList   = api.DataDragon.Champions.GetAllAsync(currentVersion).Result;

      } catch (RiotSharpException) { // Exception bla bla }
    }

   public IEnumerable<CurrentGameParticipant> getEnemyTeam()
   {
      // Get the 10 participants in the current game.
      List<CurrentGameParticipant> currentMatch = 
      api.Spectator.GetCurrentGameAsync(Region.Euw, summonerObject.Id).Result.Participants;
      
      // Get the ID team that summonerName belongs to.
      long teamId = currentMatch.Where(p => p.SummonerName == summonerName).First().TeamId;
 
      // Return the (5) participants that doens't belong to the same team than summonerName.    
      return currentMatch.Where(p => p.TeamId != teamId);
   }

   public string getImageUri(long championId) =>
      // Return the uri to load in the pictureBox.ImageLocation propriety
      uriImage + championList.Champions.Where(p => p.Value.Id == championId).First().Value.Image.Full;
}
```
\$\endgroup\$
3
  • \$\begingroup\$ string key need less than minute to get the key from the compiled executable file. \$\endgroup\$
    – aepot
    Jun 21 at 3:54
  • \$\begingroup\$ Sorry, what do you mean? @aepot \$\endgroup\$
    – Omar
    Jun 21 at 3:55
  • 1
    \$\begingroup\$ I mean storing api key in a constant string is insecure. \$\endgroup\$
    – aepot
    Jun 21 at 5:39
5
\$\begingroup\$

=> instead of the { }

This is personal preference. My preference, for example, is to generally use { } because I like it more, stylistically. I will say if it's more than a line, using => (again, in my opinion) becomes hard to read

I'm not pretty sure about the keywords const and readonly

const is used for compile time constants and readonly are for things that are set when the object is constructed. This can be either on a field or property that is initialized (ie set) where it is declared OR set in a constructor. You also can't use const with objects that you have to new. For example, you can't do private const List<string> _someList = new List<string>().

From what I see here, championList, summonerObject, and api can all be readonly.

correct way of using a Key api

Depends on what you're doing. Since you're asking about it, it sounds like you are deploying this somewhere (and possibly have this code in a repo somewhere that is available to others). You should not have the secret stored in the repo. Going in depth for what you should do is a bit out of scope for an answer here.

good practice tips

Since this is a small snapshot of your application, I'm going to make a few guesses.

You're abusing async calls here quite a bit by just putting .Result on the end of each call. The reason you need to do that is you can't make the constructor async. Since you don't need any of that information that you're getting in the constructor in the constructor itself, you can do what's called "Lazy Load" the information later. Essentially, you check if you have the object before you use it (if it's not null) and, if you don't, you get it.

Making this change pushes all of the api calls to getEnemyTeam, which should be async already (public async Task<IEnumerable<CurrentGameParticipant>> getEnemyTeam()) and change lines where you use .Result to use await instead.

From the sound of the class GameApi, it's not meant for a single summoner but a single instance could check any number of summoners. Instead of passing a single summoner to the constructor, you could pass it in to whatever method you would need. Same goes for the region, for example. Instead of hardcoding it to a single region, you could pass it in (but if it's for your own use and that's your region, so be it).

You don't need to do separate Where and First clauses here: currentMatch.Where(p => p.SummonerName == summonerName).First().TeamId. It can become currentMatch.First(p => p.SummonerName == summonerName).TeamId. As an aside, what if you pass in a different casing of summonerName than what's expected? Instead of using ==, you can do summonerName.Equals(p.SummonerName, StringComparison.OrdinalIgnoreCase).

The way you are getting the image URI, you could consider using a Dictionary. Also, here again, you can combine the Where and First methods. I also, personally, would break up that method to use { } and split it to multiple lines for readability.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks a lot for all these tips and corrections. I have felt that I learned a lot from your reading. Would you mind going a bit in depth with the subject of the key? (Any link or methodology name is enough, so we dont have to go out of scope) Thanks a lot! :) \$\endgroup\$
    – Omar
    Jun 21 at 4:14
  • 2
    \$\begingroup\$ @Omar I'll do my best but when I usually deal with secrets, it's at the enterprise level and I have certain technologies available that you might not have. You could inject a secret a few different ways. If you encrypt the value and have the certificate available to you wherever you are deployed, you can decrypt at run time. You could also inject it with an environment variable on the machine you are deploying to. If you're running in a docker container, you again can use an environment variable. I don't have much advice beyond that though. \$\endgroup\$
    – Trevor
    Jun 21 at 4:22
  • \$\begingroup\$ It's enough, thanks a lot! \$\endgroup\$
    – Omar
    Jun 21 at 4:25
  • \$\begingroup\$ @Trevor using Expression-bodied members => over curly brackets {} it's a mix of personal preference and compatibilities. (supported on C# 6 and above). docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… \$\endgroup\$
    – iSR5
    Jun 21 at 10:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.