Beginner Programming Mistakes and Why You're Making Them

Discussion in 'Spigot Plugin Development' started by Choco, Oct 14, 2017.

  1. Choco

    Moderator

    One of the points listed in the Premium Resource Guidelines is as follows:
    This is a controversial point and often leads to disappointed developers when their resource is rejected with the reasoning "beginner programming mistakes". These resources are uploaded far too commonly and is often the result of a developer that has their eyes set on money rather than quality code.

    But what are beginner programming mistakes? What do we look for as resource staff when inspecting your premium resource? What should you keep in mind when writing your code? Keep in mind that mistakes are often at the discretion of the staff member reviewing your resource, but let's assume the toughest staff member is reviewing your code. Here are the things you should avoid when publishing a premium resource.

    1. Static Abuse
    Oh the static keyword. Every beginners favourite modifier because it lets you access a method or field from another class easily! What could be simpler than just making a method static so you can use it in your listener classes? Pro tip: That's not what static is meant for. Far too often I see static being used to access a field from another class, particularly Collection and Map implementations, as well as an instance of the main class. This is a common mistake for new developers and poses some serious issues in terms of code design and flexibility in the future.

    Don't get me wrong, there is a time and place to use static, and these are some of the common situations in which it is acceptable:
    • Creating a constant field... public static final int CONSTANT = 42;
      • Constants ensure that this value is always set to 42, no matter what
      • If a single (non-changing) instance of an object is required, it's best that it's static and constant
    • Declaring a (proper) singleton pattern
      • If only one instance of a class should be enforced, use a singleton pattern. A REAL ONE. Not an "I need an instance of this whenever, let's make a static getter". That is not a singleton
    • Utility methods
      • A common feature that people often confuse as static abuse are utility methods
      • A method that requires no instance at all and exists solely for the purpose of providing utility throughout the project may be declared as static
    Any other use of the static keyword is likely going to be identified as static abuse, but it really depends on the context. If I have forgotten any, please do let me know. It all narrows down to the point that if you're using static as a means of accessing something, you're using it wrong and your resource will be rejected.

    1.1 Singletons
    Singletons are a huge point of debate, especially given that the main class (the one that extends JavaPlugin) is a singleton. I often see people defend their use of static fields / getters in the main class because it is a singleton. JavaPlugin has a method to obtain a singleton instance of your main class, JavaPlugin#getPlugin(Class<T extends JavaPlugin>). If you really want to use the argument that the main class is a singleton therefore creating a static field / method to access an instance is okay, then at least use the proper method to do so. With that being said, static getters for an instance of your main class have been a staple in the majority of plugins, but if you were to create one, use it when absolutely necessary.

    The above argument should be taken with a grain of salt. MinecraftServer (the class that controls the vanilla Minecraft server) is also a singleton and has a static getter method. As does the client class "Minecraft". Nevertheless, while they do have static methods to retrieve an instance, constructor dependency injection is used where possible. These are well-defined singleton patterns. When it comes to a plugin's main class, a static getter should be used as a last resort where dependency injection either does not make sense or is impossible to use. This argument is aimed primarily at beginners to lack the basic understanding of the static keyword.

    Main class aside, singletons should only be used when only a single instance of a class should be enforced. For example, if you have a runnable that is to be executed in your onEnable() method, but you only want it to be executed once by your own plugin, a singleton is likely the way to go to ensure that no other resource is capable of executing it. Keyword, "enforce". If you're simply creating a static field and getter method, this is NOT enforcing a singleton pattern. Reading up on how to use the singleton pattern is recommended before using it.​


    2. Repetitive Code Blocks (DRY Principles)
    Many beginners lack some basic programming knowledge and make the mistake of breaking the Don't Repeat Yourself (DRY) Principles. As the name implies, if you have to constantly copy and paste code with different variables or method parameters, you're likely doing something wrong and you need to re-evaluate your plugin design. This is frequently executed in "pet" plugins.
    Code (Java):
    public void spawnPet(String pet, Location location) {
        if (pet.equals("Bunny")) {
            Entity entity = location.getWorld().spawnEntity(location, EntityType.RABBIT);
            entity.setDisplayName("Bunny Pet");
        }
        else if (pet.equals("Cow")) {
            Entity entity = location.getWorld().spawnEntity(location, EntityType.COW);
            entity.setDisplayName("Cow Pet");
        }
        // etc. etc. etc.
    }
    There are a number of things wrong with the code identified above. For one, your entire code-base relies on Strings rather than some sort of Pet object (further detailed in "Lack of Understanding of OOP"), and you're creating a bunch of if and else if statements checking if the String is equal to some value only to accomplish a very similar task. Lastly, there is no global variable for Entity and #setDisplayName() is unnecessarily invoked more than once. The overall design of the aforementioned method is so poor that the entire project would be based around what we like to call Spaghetti Code. The project will eventually get too large all the while depending on a messy, String-based system that can be extremely repetitive and lengthy.


    3. Lack of Understanding of OOP
    As many of you know, Java is an Object-Oriented Programming language (OOP) that relies largely on 4 basic concepts:
    1. Abstraction: Exposing specific and core features of an entity while hiding less important or sensitive information from the end-user
    2. Encapsulation: Hiding values from public access and creating getters/setters to force users to interact with your data in a safer and more controlled state. Mutability and data control.
    3. Inheritance: Understanding that classes can inherit members and methods from super/parent classes
    4. Polymorphism: Changing a value or a method's functionality at runtime from a parent class. Completely redefining a method if a different implementation is used.
    A lack of understanding of OOP generally boils down to developers that do not want to spend the time to properly learn Java, but rather jump directly into Minecraft development. Please listen to people on the forums when they tell you to learn some basic Java. It is a fundamental concept that you must understand, even if it's just the basics. Know enough to understand when, where and how objects should and should not be used.

    3.1 Poor Code Design / Structure
    As mentioned in Repetitive Code Blocks, if your project relies entirely on a poorly designed code-base, you're going to struggle when maintaining your code in the future. Your code will get messy, it will be difficult to work with, and you'll end up having to bend over backwards in order to miraculously get your code to function as intended. Your final project should be OOP friendly and avoid relying on basic Java concepts, ultimately ruining future maintenance on the project.

    3.2 Keeping Everything in a Single Class
    Unfortunately, this is seen just as frequently as poor code design. If your whole code-base is set completely in a single class of 3,000 lines, it's likely that your project will be instantaneously rejected. Right then and there I can tell that you do not understand OOP, you are not willing to learn, and you cannot manage to properly organize a project. If you have everything in a single class, start moving things to different classes and modularize your project. Listeners can be grouped into new classes, commands into their own separate executors, and basic Plain-Old Java Objects (POJOs) to clean the code and improve your programming style.

    Under no circumstances should your project be less than 3 - 4 classes. This applies to both premium resource development as well as professional-grade development. You cannot simply keep everything in a single class file. Your project will become too unreadable. Imagine Apache Commons Lang3 in a single class... No one would use it

    4. Missing Basic Knowledge of Java
    Lastly, one of the things people tend to miss the most is the basic knowledge of Java itself. If your programming habits are so poor and far-fetched, it's likely that your resource will be rejected. What programming habits do we expect? Sure, everyone has their own preferences, but there is a minimum code standard set by Oracle that you should follow. Here are some examples:
    • Class, method, package and variable names have their own naming schemes
      • Classes should be named in an UpperCamelCase scheme
      • Methods should be named in a lowerCamelCase scheme
      • Packages should be named in a lowercase scheme and under your domain backwards (i.e. com.google.<project>)
        • If you do not own a domain, either use com.github.<username>.<project> or me.<username>.<project>
        • Heed from using a domain that you do not own! This leads to confusion when a user is seeking support.
      • Fields should be named in a lowerCamelCase scheme, EXCEPT
        • When fields are constant (static & final), in which case they should be UPPER_CASE
    • Misunderstanding the usage and drawbacks of the various access modifiers including public, private, protected, static, final and so on and so forth
    • Constantly repeating the same code rather than creating a method to execute common features
    • Blindly casting objects without first checking instanceof
    • Using primitive wrapper classes rather than primitives themselves (i.e. Integer vs. int)
    A basic understanding of Java can go a long way, and simply missing out on minor code standards can cost you a premium resource approval. A lack of programming standards (whether they're Oracle's or your own) will result in messy code and low readability.

    5. Conclusion
    In conclusion, yea, your resource was rejected for "beginner programming mistakes". So what? This is a time for you to take this opportunity to look over your code and try to better yourself. Accept the fact that your resource was rejected in the premium queue and try your hardest to find something that can be improved upon. If your resource was rejected, look over the things listed above and make a little checklist. If you're struggling with Java and basic concepts, take a step back to learn the language before continuing to program plugins. It will help a great deal and you'll have a premium resource in no time.

    If anyone has any further questions or believes I have missed something in this list, please do let me know and I'll try my best to add it. I understand that there is a character limit on threads, therefore if I need to, I will edit the post below me to continue upon this thread. I would be more than happy to answer any questions you may have and whether something may be considered beginner programming mistakes or not. Do not hesitate to ask. I hope this little "guide" helped.

    NOTE: The points listed above are of my own opinion. Other resource staff may pay attention to different features. It should be noted that what I look for may not be the same as what other resource staff are looking for.
     
    #1 Choco, Oct 14, 2017
    Last edited: Oct 10, 2018
    • Informative x 20
    • Winner x 13
    • Agree x 5
    • Useful x 5
    • Like x 4
    • Funny x 1
  2. Choco

    Moderator

    (reserved for any future edits)
     
  3. Nice thread, hopefully this will get stickied.

    be*
     
    • Like Like x 1
  4. MiniDigger

    Supporter

    This should say rejected instead of designed.

    Anyways great post, while I don't agree with 100% it sure is a good guideline.
     
    • Like Like x 1
    • Agree Agree x 1
  5. Very useful. Highly recommend all developers to read it. Regardless if they’re posting a premium resource or not.
     
    • Agree Agree x 2
    • Friendly Friendly x 1
  6. Problem is people really don't get it they just want to jump out and start coding a "bukkit" plugins while having 0 knowledge on understanding basics of OOP and java as well.

    PLEASE LEARN JAVA BEFORE MAKING ANY BUKKIT PLUGIN.
     
  7. MiniDigger

    Supporter

    you can learn java while making plugins, I did learn java while modding and many others did the same, just don't upload your first plugin to spigot and sell it.
     
    • Agree Agree x 9
    • Like Like x 2
  8. Nice thread :p
     
    • Friendly Friendly x 1
  9. Choco

    Moderator

    Yea... see I blame this on making the thread at 1:30 in the morning and not having the energy to proof read before publishing it. Haha. Thanks. I'll change these right now.

    Also, for @MiniDigger, yes. I can see why people won't agree with 100% of what I wrote above, but this is what I look for when I'm reviewing a premium resource. It's just some very very very basic stuff that I expect in a premium resource. The problem is that I can't include every single mistake someone makes in a tiny little rejection alert in the top right corner, so I have to just write "Beginner Programming Mistakes". Hopefully this acts as a place to go if someone had their resource rejected for that reason.

    Although I agree, Java is an essential tool to making a Bukkit plugin, I actually did the same thing. I learned Java whilst creating Bukkit plugins. The thing I did differently than most people is that I took my time to actually learn Java as well as the Bukkit API. I watched and read tutorials on Java, and if I didn't understand something in a Bukkit tutorial, I would see if perhaps I could learn something new about Java. The issue comes when people try to learn Bukkit thinking that it's Java. It's not. They often don't separate the language from the API at all and just think it's normal. I've seen some people attempt to make basic Java programs and use onEnable() and an entry point.

    TL;DR: It's certainly possible to learn Java as you learn Bukkit, just learn them separately. Don't learn Bukkit faster than you learn Java.
     
  10. All part of the fun, eh? I've been coding spigot plugins for 3 years. I still look back at work I did 3-6 months ago and think. "Who the hell wrote that... Moron.." and end up rewriting it. All part of developing.
     
    • Agree Agree x 4
  11. MiniDigger

    Supporter

    I have seven years of experience and the same happens to me. If that stops happening, you stop learning which will mean you will be out of the loop pretty fast.
     
    • Agree Agree x 2
  12. Exactly
     
  13. This is a really usefull thread. Thanks for the information :D
     
  14. Thanks for the hilo. This helps me!. Now i understand new things.
     
  15. I think it's easy to say "learn java first", but a lot of people need solutions for situations they are in now, and while they're learning how to use the right things in the api, they're learning java to make it all work.. I can totally understand this. No need to spend months and years to master java just to please those who should "learn that first MEH" for a 12 line plugin code. This doesn't mean that i disagree with it, but i think there's a valid argument in that people need solutions now, not in 3 months or next year..
     
    • Winner Winner x 1
    • Informative Informative x 1
  16. I'm not a java developer, though I am a web developer, so I may be wrong, just please correct me if I am.

    From my stand point, I don't think you NEED to learn Java first before coding your first Bukkit plugin. If I were to start coding plugins, I'd rather start learning a couple basic things about it, fuss with it a bit (not too long), and start coding my first java application using Bukkit/Spigot APIs. I wouldn't necessarily start a plugin from scratch without playing with Java a bit (though I have learned JS before, and they are similar in some ways), as that would be super dumb and I wouldn't know a single thing about what a constructor is when I need help. My first plugin that I attempted to make was supposed to set the spawn point of the world and the command /spawn. That failed, and I just couldn't keep up learning Java with everything else that I have to do in life. So this guide will probably help me in the future when I decide to start coding plugins again. Who knows. ;)
     
    • Funny Funny x 1
    • Winner Winner x 1
  17. How did Crackshot Plus get premiumized? The plugin before version 1.x is crappily written.

    And if the owner of the plugin is asking how I got the plugin. I got it from the server I’m developing for. The owner gave it to me to update it to extract the version dependent code to our Internal API.
    This was needed because the crackshot plus developer didn’t write a configconverter.
     
  18. Choco

    Moderator

    I was not a resource staff at the time, I have the slightest of clue.

    That’s fine, but don’t publish your horrible code as premium expecting it to be approved. If your code quality is that of a beginner, it’s just not happening :p
     
    • Agree Agree x 1
  19. Legoman99573

    Supporter

    Some people do learn java through bukkit or if you learned javascript, which some methods can be applied to java.
     
  20. I've just spent more time developing a clear chat plugin than anyone has ever done before, the difference is that it contains 0 loops, with over 3150 lines! is it possible for me to publish it as a premium resource ?
     
    • Winner Winner x 1