Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (109)
games submitted by our members
Games in WIP (536)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  basic question on libraries  (Read 1778 times)
0 Members and 1 Guest are viewing this topic.
Offline Kommi

Junior Member




All opinions will be lined up and shot!


« Posted 2005-11-22 18:01:48 »

Can some one give me a 1000 foot definition of how you write code as libraries so as to make it modulized and reusable? Any high level examples are welcome.

Kommi
Offline Jeff

JGO Coder




Got any cats?


« Reply #1 - Posted 2005-11-22 23:35:53 »

Its called a "data structure" Smiley  Understadn that and the rest is just details and learned esthetics and technique.

A Data structure is the encapsulation of a set of data, organized in some way, and the routines to access and modify that data.

Structured programmign 101.  Object oriented code doesnt chnage that, it just gvies you more refined ways of managing data structures.

In general, I'd recommend you read Josh Bloch's book "Effective Java" as it will give youa lot of guidance on how to do this well in Java.

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Offline kevglass

JGO Kernel


Medals: 122
Projects: 23
Exp: 18 years


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #2 - Posted 2005-11-23 02:02:15 »

Wow, what a great question!

Library programming is imho is more about defining the contract between user and and library than anything else. Be sure of what you're trying to provide/manage and be clear in your documentation.

Kev

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #3 - Posted 2005-11-23 05:22:46 »

Yep.  I've designed several APIs in the past and it is all about a clean definition of the interfaces involved.  Hiding implementation details where ever possible, but being sure to make them explicite when they really matter.  Always imagine at least two completely different ways the library could be used (i.e. put yourself in the shoes of two potential users, each with different goals) and use that as a basis for making the interface reasonably generic in the context of the library.

Offline cylab

JGO Ninja


Medals: 38



« Reply #4 - Posted 2005-11-23 09:43:47 »

If you want to make an expandable library you might condsider splitting up your library in three parts:

- API
- SPI
- Implementatation

The API (Application Prorgamming Interface) consists of the interfaces and basic data type classes you would like to provide. To create real instances of the implementing classes you should consider using the abstract factory pattern (meaning creating the instances by a "factory"-class with some createXXX()-Method instead of directly calling constructors).

The SPI (Service Provider Interface) contains all the neccesary bits for implementing modules in your library. It mainly consists of abstract base classes that implement one or more interfaces from the API and a set of helper utilities.

The Implementation is what it's named: the concrete (standard)-implementation of your API ;-)

An API of such a design would look like:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
    // The Interface defined in your API
   public interface Foo
    {
        public void methodA();
        public void methodB();
        // Added after Implementation of ConcreteFoo
       public void methodC();
    }

    // The base class defined in your SPI
   public abstract class AbstractFoo implements Foo
    {
        public abstract void methodA();
        public abstract void methodB();
        // Provide some default implementation to prevent a Rewrite of existing modules after methodC() was added
       public void methodC(){ /*some default behaviour*/ }
        protected Object getNonAPIDetail() { /*some functionality not intended for the API User*/ }
    }

    // The concrete implementation
   public class ConctreteFoo extends AbstractFoo
    {
        public void methodA(){/* do something useful */};
        public void methodB()
        {
            // utilize the extra functionality provided by the SPI
           Object bar= getNonAPIDetail();
            /* do something useful with bar*/
        };

        // this method was part of the SPI, but was removed later...
       public String getIdentity()
        {
             return "Foo";
        }
    }

    // The Factory Singleton in your API
   public class Factory
    {
        // The static instance for sharing
       private static Factory instance=null;

        // A protected constructor forbids direct instanciation by the API user
       protected Factory(){}

        public Factory getInstance()
        {
            if(instance==null)
                instance= new Factory();
            return instance;
        }
       
        // The factory method to create a Foo based on system property configuration
       public Foo createFoo()
        {
            try
            {
                Class myFoo= Class.forName(System.getProperty("your.api.package.Foo"));
                return (Foo) myFoo.newInstance();
            }
            catch (Exception e)
            {
                System.err.println("Could not instantiate Foo implementation: " + e.getMessage());
            }
            return null;
        }
    }

    // To create an instance of your Foo class
   Foo aNewFoo= Factory.getInstance().createFoo();


As you can see, the separation of API and SPI enables the library author to add more interface methods over time without breaking the module developer contract, since they only depend on the AbstractFoo base class. A similar effect can be seen for the "getIdentity()"-method in ConcreteFoo, which was an abstract method of the SPI but was removed from the base class at some version to be replaced by another identification mechanism, that does not depend on this info from the concrete implementation anymore. Both modifications did not break the contract between the user and the library nor between the module vendor and the library, so long term binary compatibility can be archived.

Since the API-user should not need to know anything about the concrete implementation, the Factory just deliveres an instance of the API Interface. Which class is instanciated can be configured using a system property, so you can replace the API-Implementation by specifying a different concrete class in the property without touching the users code. Normally you would use a configuration file or something instead of a system property, but this is just an example Wink

Also keep in mind, that using a factory for every single type in your library is probably not the right way. There can be a lot of simple classes in your API, that don't need the abstraction and exchangability feature, as well. However, the factory pattern as described above is best suited for component/module instanciation.

Mathias - I Know What [you] Did Last Summer!
Offline kevglass

JGO Kernel


Medals: 122
Projects: 23
Exp: 18 years


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #5 - Posted 2005-11-23 15:02:11 »

SPI strikes me as its approaching golden hammer status. Its useful in some cases where you want that level of flexibility, in most library cases its just massive overkill.

Kev

Offline cylab

JGO Ninja


Medals: 38



« Reply #6 - Posted 2005-11-23 15:05:44 »

You don't have to provide a SPI layer for everything, but having it for a limited set of module-/component-interfaces is a Good Thing (TM). For example it might be a good idea to use an SPI layer for something like a plugable scenegraph renderer, but it makes little sense to use one for new geometry-types to be added to a scenegraph, for which simply implementing a generic Geometry interface is sufficient (and probably much better).

Mathias - I Know What [you] Did Last Summer!
Offline Niwak

Senior Member


Medals: 1
Projects: 1



« Reply #7 - Posted 2005-11-23 16:47:28 »

From my point of view, SPI are usually a design error ; they promote implementation inheritance as a good design practice which, I think, is completely wrong.

The more simple design pattern with interface on one side and implementation on the other seems the good way to go for me.

Your client should never be in a situation were it has to read your implementation to use it. SPI will create such a situation.

For the API I design, I tend to try to apply this design rules ;
     . keep it simple and readable
     . keep classes and interfaces "short" (i.e. avoid interfaces with 30 methods, classes with hundreds of lines of code,...)
     . build a readable package architecture (avoid packages wih too many elements, avoid mixing definition package with interfaces and implementation packages with classes)
     . prohibit package cycles
     . restrict class cycles to the minimum
     . keep it flat (i.e. limit the number of levels of inheritance)
     . discourage implementation inheritance (in fact, implementation inheritance is only allowed for ultra-stable classes fo which I am completely sure that the contract willnot evolve, and even in this situation, it is only allowed in the internals of the library)
     . prefer composition to inheritance

One thing I would love to have in Java is "design by contract" (search for Bertrand Meyer book on the subject) wich gives a very good and safe way to design your library but it's still missing.

      Vincent

Edit :
the example of the pluggable scenegraph renderer is clearly a situation where I would not (and I do not in my 3d engine) use a SPI. If you want your scenegraph renderer to be pluggable, I think you should clearly define the contract of your extension point in extension point interfaces and provide an extension registering mechanism.

example :

SPI :

public abstract class PluggableRenderer {
 
    [...]

    protected void visitNode(INode node);

    [...]

}

Result : everything is mixed, the resulting design willnot be reusable, your plugin won't be reusable for another renderer.



Composition with interfaces :

public interface INodeVisitor {

    public void visitNode(INode node);

}

public class PluggableRenderer {

    public PluggableRenderer(INodeVisitor visitor) {
         [...]
    }

}

Result : the design is readable, your plugin is reusable.

Note : I know this example is very simple but you can go further this way. For example, my renderer use plugins for visiting nodes based on their node Id. The overhead for this is near zero since the design use a simple array access to get the plugin for the appropriate node.
This lets my plugin be shared between the different scenegraph visitors.
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #8 - Posted 2005-11-23 17:34:28 »

Your client should never be in a situation were it has to read your implementation to use it. SPI will create such a situation.

I don't see the connection.  Care to elaborate?

Offline Jeff

JGO Coder




Got any cats?


« Reply #9 - Posted 2005-11-24 01:06:21 »

Good library design is as  much an esthetic as anythign esle, and exaclty what consittutes "good" chnages depending on your audiance.

Game develoeprs want lean, mean and efficient.  If you cna make my job easier great but NEVER totally take away control from me or force me to use up CPU cycles where I don't want to.

Eneterprise develoerps want it as automated, idiot proof, and simple to use as possible and don't care much about control and only limitedly about performance, really.

A good general rule of thumb for any tool is this:
"Doing the simpelst 80% of the use-cases should be easy.  Doing the last, hard 20% shouldn't be any harder then doing it without your tool and ideally shoudl be easier."

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline darkprophet

Senior Member




Go Go Gadget Arms


« Reply #10 - Posted 2005-11-24 02:02:51 »

Treat your users as if they were 5 year olds?  Roll Eyes

Always worked for me...

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
Offline cylab

JGO Ninja


Medals: 38



« Reply #11 - Posted 2005-11-24 10:02:32 »

+1 Jeff
+1 darkprophet

I have rarely seen a pair of comments, that expressed more, which kind of fight is going on in my head  Grin

Mathias - I Know What [you] Did Last Summer!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CogWheelz (18 views)
2014-07-30 21:08:39

Riven (24 views)
2014-07-29 18:09:19

Riven (15 views)
2014-07-29 18:08:52

Dwinin (12 views)
2014-07-29 10:59:34

E.R. Fleming (33 views)
2014-07-29 03:07:13

E.R. Fleming (12 views)
2014-07-29 03:06:25

pw (43 views)
2014-07-24 01:59:36

Riven (43 views)
2014-07-23 21:16:32

Riven (30 views)
2014-07-23 21:07:15

Riven (31 views)
2014-07-23 20:56:16
List of Learning Resources
by SilverTiger
2014-07-31 18:29:50

List of Learning Resources
by SilverTiger
2014-07-31 18:26:06

List of Learning Resources
by SilverTiger
2014-07-31 13:54:12

HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!