Showing posts with label project dune. Show all posts
Showing posts with label project dune. Show all posts

Tuesday, August 19, 2008

AI ambience or collective web intelligence?

I've been busy a lot with some administrative things. In september classes are starting and I'm commencing with A.I. Registrations are done, just register for a couple of courses and go. There's a new direction for the next year: "Human Ambience". I had quite some interest into intelligent systems, but I do like ambient intelligence as well. I think it's really done well when you don't notice it at first, but then later go: "oh, that was actually pretty cool!".

For the rest Project Dune is trucking on as usual. I'm preparing a plan for a manager of the company I work for to possibly spend a bit of budget on getting the project a little bit further, but then with the help of the effort of some colleagues. All done open source of course. So that's exciting.

I'm also looking at perhaps providing a Java API to interface with CUDA. The objective is to make it available to Java users. Not sure how to write the "java" program and compile that for CUDA use though :).

Tuesday, July 15, 2008

Work on roadmaps, sw engineering, technical debt

Project Dune is developing a new roadmap for the last half of 2008 and to kick off 2009. Being open-source, you can always read the latest developments on the project wiki.

Part of the roadmap now became strategy, which will probably be moved out to the start page close to the mission, thereby making the roadmap a practical guide of where something is going and why, without necessarily focusing too much on the actual activity.

Another part of the roadmap of Dune is the initiation of a set of processes, practices and tools / checklists / material to support the process of software engineering.

A particularly interesting term that was coined by Ward Cunningham is the term technical debt. As a quote from the wikipedia site:
The analogy to financial debt is that the poorly-written code requires "interest payments" of maintenance effort, which would be smaller or non-existent had the code been developed more carefully and with better long-term planning. Rearchitecting and rewriting the code to be more maintainable is analogous to paying off the debt principal.
Other sites:

http://www.agileadvice.com/archives/2006/12/technical_debt.html


http://forums.construx.com/blogs/stevemcc/archive/2007/11/01/technical-debt-2.aspx

The graphs here are very good examples of the consequences:
http://kanemar.com/2006/07/23/technical-debt-and-the-death-of-design-part-1/

As part of Project Dune, I'll need to think about how to come up with practical guidelines for software quality and explain these terms in more detail, probably with extensive use of links. The idea is to become the main site where people look for quality information. That should include links and understanding about software engineering, development, language choices, etc... Ideally documented in such a way that it goes from a high-level overview to a detailed overview.

The first objectives are to come up with a generic process / vision of software engineering itself. This is no easy feat! It's difficult enough to align people on the same vision within a single team as there are always people that have different opinions or people that have the thorough conviction that things are done better in a different method.

Thus, the idea is not to suggest "Agile Development" or any other more specific method for software engineering. It should go one level above all this and just state the following:
  • Objectives of the activity
  • The activity's function
These two sound exactly the same, but are somewhat different. The objective is basically what you're trying to achieve. The function is what you're trying to prevent/discard during that process or what you should pay specific attention to.

I'm wondering whether project managers in SW projects nowadays have sufficient knowledge of project analysis and the terms used for sw engineering to be able to steer back to a winning situation. If you look at the term "technical debt" for example, its actual scope is quite large. Besides technical debt though, there are other reasons why projects fail, which are more on the area of communication and social interaction (the requirements need to be correct).

A good initiative for the Dune project would be to try to come up with 2 or 3 main areas and coined terms that contribute to project failure. Then subdivide the areas and identify the causes.

The idea being that the identification of root and main causes for project failure (and supporting cases?) would clarify the need and use of certain activities in a project. I'm not using the term process, as I'm not too fond of that term how it's interpreted in general. Activity means something that a tester/developer carries out as part of his job or task and which is easily part of a process. The process is thus basically a sequence of activities done with a number of available tools and materials, nothing more. Understanding the process thus doesn't mean how to comply with some corporate or industrial standard. It means that you understand what you're doing and how that fits in the big picture.

Saturday, June 14, 2008

EK & GWT

Holland is playing really well in the EK. It's a joy to watch. Got 6 points in the pocket and all of Europe is commenting how well-greased the team is playing this year. I'm expecting Holland to win this EK.

Well, for something totally different, a new version of GWT is out, 1.5. The beta version has good new capabilities and standard themes that prove very useful. I'll be plugging that into my project and keep improving the user interface. Then probably release 1.5.1 before I'm hosting a demo next month at the company I work for, in front of project managers, architects, testers and other people.

Thursday, May 01, 2008

Cocomo II implementation on Project Dune

As discussed in previous posts, I've been designing an approach for Cocomo II software project estimations. The implementation has already been added to Project Dune on the main branch and is destined for finalization into a new major version of the project, Project Dune 2.0.

The first step in estimation is to determine the project size:

http://gtoonstra.googlepages.com/sizing.png

The next step in this approach is to determine the effort multipliers. Those multipliers increase the time required to develop something linearly.

http://gtoonstra.googlepages.com/effortadjustment.png

The scaling factors in the next tab increase effort exponentially, so if those end up really high, the effort required is soaring as well:

http://gtoonstra.googlepages.com/scalefactors.png

After the factors are supplied, the outcome of Cocomo II is a set of numbers. The most useful numbers at this time are listed here:

http://gtoonstra.googlepages.com/result.png

Notice in the different screenshots how the factor being manipulated is explained in the tooltip. The text in the middle is a reflection of the correct assessment of that factor.

The results show the person-months that are required to develop the project, the nominal person-months (if all scale factors and multipliers would be nominal), and the Time-To-Develop together with the number of staff required to implement the project.

Wednesday, March 05, 2008

Project Estimation

There are some interesting discussions taking place on project estimation. Project Dune 1.4.2 came out yesterday, where you can register your estimates per activity per scope statement. So that's basically "ballpark" level of detail.

There are some new requirements that are coming up that look really interesting. PM's really seem to (want to) use some kind of math magic to get to certain numbers and then tweak them.

So, what really matters in a project? What are factors that, if they change, significantly affect the timeline of a project?

I've already mentioned that the level of communication is a huge issue. So, if your team increases, you'll increase contention within the team, the need for communication (which loses time) and so on. Especially at the start, where the PM actually intended to move fastest. So the rest of the trajectory people are generally told to "get on with it", leading to unsatisfiable levels of communication and lower standards of quality.

Oh well! :)... Expect some more notices in the future with regards to this topic.

Saturday, February 23, 2008

Screenshots and features Project Dune

I took some time to update the projectdune wiki with a list of features currently supported. That should make things a lot clearer. See the screenshots for further details.

Supported features

Monday, February 18, 2008

Cold!

Err... yeah, it's been cold in Holland for the last two days. Icy, salted roads and scratching ice from car windows. It'll improve very soon though.

I worked on Project Dune over the weekend and it's now getting there. One more bit of functionality to create the reporting ability from estimate to timesheet. That'll certainly mark a milestone. From there onwards as they say. I'm trying to take things easy now and just improve on existing things. Maybe some refactorings here and there.

There's still a new module in the pipeline for test case management. So you can write a document, the test plan and then refer the individual bits with the test results. The same things should probably be done for issues.

Wednesday, February 13, 2008

Identity on the Net

Project Dune has a feature implementation pending with regards to logins through OpenID's. When you surf the net nowadays, every site you go to requires you to put your details in for registration. The objective of registration is to be able to verify the same details at a later time. The details are verified by a secret that you are telling in the process of registration (your password), which is stored securely at the site and of which both parties hope is a secret that is never shared with any other party.

Your registration however is further verified by adding a key that you only own: your email address. The registration site creates a temporary link with a complex url that is very hard to guess. You move to the url and thereby activate your account that you requested to set up earlier. From here on, you don't need to keep checking your email to be able to log in, you use the shared secret.

What most sites care about is authentication. Authentication is the process of verifying that someone who identified himself with some token at some point (your name or any other credential) is the same person that comes back another time and not somebody else. This is essentially what authentication means for sites that allow "semi" anonymous access (you register with your details, but the registration site never actually verifies your real identity. So what they check is not that you are who you say you are, but that you are the same person that made the initial registration).

OpenID attempts to simplify this a bit further. Rather than "registering" in the same method for each site that you may be on, you'll continue to see new sites popping up that claim to manage your identity online. Basically, this means a split of the registration process from the authentication process.

Remember how I said that many public sites don't care about who, in the context of real identity, is making a registration? They only care if they can reliably assume that it is the same person that actually registered before. So another site could authenticate on the site's behalf and then have the user call back to the originating site with the result of the authentication.

The authentication relies on the fact that the user now claims to own a url. For example, if I want to log on with OpenID on a forum site, I could claim I own:

http://gtoonstra.blogspot.openid.com.

Then the forum site tells me: "oh yeah? proof it!". So they redirect my browser to an authentication provider site "gtoonstra.blogspot.openid.com". The forum site passes in a return URL that is used to pass my browser back after the authentication claim. First, I need to fill in my secret that I have with my authentication provider. If I succeed, it is assumed I correctly own the URL. If it fails, my claim is invalid.

In both cases, I get redirected to the forum site. The forum site then analyzes the details and shows the results as they have programmed. There's another process there related with cookies and multiple redirects. So if you have already logged on with your OpenID, a cookie is stored in your session. Then for each site that you visit, you may be requested how long you wish to keep the cookie and the session. As you get redirected from one site to the other, the sites still redirect you to your authentication provider inbetween to re-verify the details. This process is called "single sign on".

Project Dune thus will start to use OpenID. The objective is to modify the project code to allow anonymous browsing for "the public". So you won't have the same abilities as users created through the system, but you can still browse issues and participate in those things that the administrators have indicated as allowable.

Now, consider the options here. Project Dune for example contains functionality for inspections. This means you could configure the software to allow people to participate in inspections of source code. How cool would it be to have anonymous users inspect your code online for certain changes and make remarks? The current method is mostly by sending email, but this way you just login, go to the source, open it up, add your comments and move in. You are identified by your OpenID, so you will in some way be traceable.

Sunday, February 10, 2008

Project Dune release 1.3.5

I've worked a bit this weekend on a new installation method for Project Dune. Some software written in PHP is earmarked by the ability to just extract it to some web directory under Apache and run it.

Project Dune now also gains that ability. It's quite unique for Java packages, since mostly these are very manual processes. I spent quite some time to develop a web based installer. It's a war package that goes to Tomcat, where it will configure the project before it puts it in the final place for installation.

Have a look over at SourceForge and let me know your thoughts over at the forums.

Tuesday, February 05, 2008

Internet and updates to projects

I finally got Internet now. It took three months to get it all done. Alice Internet is crap. I requested it 25th October. Then 10 days later received a letter/email that my service was canceled. No reason given. I called and they said it was the register of connections where my request wasn't listed. So they tried again. Some days passed and nothing happened. I called to be sure and they said they'd restart. Went on holiday for 3 weeks. Came back. Absolutely nothing, as if the request just died. They said they'd try again and I just gave up there. So I went with KPN Comfort or something.

They said they'd connect in 2 weeks, but this became 5 in total. After 2/3 weeks, you get a call to confirm a repair man to come around. Actually, all he does is check the signal on the box and if that's allright, he leaves. So not really any use there. The crap is that only after they ship the box with the modem, so you just wait a stupid amount of time before you are connected.

Anyway, it's done now and working. 650 Mb/s effective downstream. Some 12'th of that upstream. It's stable and has good service.

I've updated Project Dune at SF now and XssProtect at Google Code. Later on, I'll have to redeploy Project Dune because it requires Java6 and has a couple of fixes here and there. Then I'll need to figure out how to get the project more popular. Probably relates to creating complete deployments or shell scripts that can do this. I'm not tooo happy about izpack, because you can't install it on a headless machine. What's the best method to create installs for software on Linux?

Saturday, September 01, 2007

Why quality plans should use wiki's

I'm writing up a lot of information in the Project Dune wiki and start to realize the potential and importance of the wiki itself. I have been browsing wiki's for some time, but now is the first time I am actually editing a lot of pages.

The Project Dune wiki is about software quality and has two main purposes. It documents the project and it documents consolidated knowledge about quality.

As I go through the pages, I experience the difference between a site with static information that is maintained by a number of editors versus a site that has freely editable information with a couple of access constraints. So when a reader can become an editor at the touch of a button, it gives the feeling (and potential) of participation. This is important for a human being and for companies to generate a sense of identity.

When a company would use a wiki to document quality plans and use the discussion and talk extensions, consider the difference in attitude that the engineers would have on the quality policy and plans (in the case of companies where only managers are owners of the policy and dictate it 100%). The question is not so much that engineers must have made a contribution on the wiki. The difference is the possibilityto suggest changes to the policy immediately and do so on the record in public.

But I don't think the wiki is immediately sufficient. I've worked in some companies that have a very archaic view of the quality plan / policy. It is probably comparable to code crush, which is when a developer becomes highly defensive against any proposed changes on the code and may get furious when he finds out that someone else messed about in the implementation. Even though the statement is often made that it's totally open and we're willing to change, it doesn't necessarily apply in practice.

It shouldn't be like that. We should consider the quality plan and policy an adopted approach documented and taken by all participants (certainly in the case of the wiki). In this view, the quality manager, managers and people that make decisions become stewards of this information. Their role isn't to judge content, it's to take care of it and continuously ensure that the group as a whole steers the quality plan and policy to better definitions.

Consider opening up your policy and plans to your internal engineers. Trust them to be able to apply common sense (or make sure they receive additional, adequate training to make better decisions). You might also want to back up your wiki with discussion forums. This way, any doubts on the policy can be cleared by other participants with the added benefit that it can also be used to document certain conversations and retain that knowledge.

Friday, August 31, 2007

Project Dune developments

I haven't been able to post much recently due to a release being developed at work, some emails from the project team of Dune and the stewardship of a new project infrastructure for Project Dune.

You can check out the forums (phpBB) already. The wiki (mediawiki) is in development and I suspect it will be released very soon.

The project has attracted a couple of new members and is now getting ready to support itself over the following couple of months. We're adding better targets, better planning, better documentation, better milestones, better interaction with the community.

Our hosting is done by SiteGround. It's the first time I do business with them, but so far things have been fantastic. Always up and their support team responded within minutes to support requests. Absolutely awesome service, awesome packages (5000GB/month bandwidth and 500GB disk space per account) and I can certainly recommend it to others. If you do, make sure that you mention us as a reference, you will help the project out with a couple of free months of hosting.

So pretty soon the wiki comes out. We'll get all the way back to development and a regular cycle of project documentation when all is done. You should also see a couple of new (active) members on the project.

Friday, May 18, 2007

Swamped...

Bit swamped at the moment, so little time to blog about anything. Will deploy a new release of Project Dune over the course of the weekend, which should include the new timesheet module. That will only be sort of Alpha-ish, since the locking functionalities won't work yet. Also, it needs a breakout class for the timesheet processor, so you can export your times reported to another system.

Well, great. We've been playing with GWT 1.4 for now. The hosted browser fixes and memory leak fixes really do help development, so you could say it really is maturing.

I'm looking forward to the suggestbox, number and dateformat classes and the Rich text editor for the document management part. Haven't had any time whatsoever to deal with HTML<->DocBook conversions though, let alone putting in place some simple templates for PDF conversions using XSL:FO.

Friday, March 23, 2007

Guice in GWT

I am separating some functionalities in Project Dune. Transaction control was initially handcoded in each service request, but there were two problems here. The service request started the transaction in an HTTP specific stub and the business logic was mixed with this protocol-specific code. So the separation puts the business code into a separate object and transaction control is managed on any method that this business object does.

The first attempt actually was a transaction filter that always creates a transaction and then closes it, but this is expensive and one problem with GWT is that the SerializableException gets consumed and serialized as a response stream. So the filter will never see this exception being raised.

I have thus used Guice (pronounce this as "juice") to deal with these problems. The way it works is like this:
  1. A servlet context listener is used (see web.xml configuration) to initialize a Guice Injector and bind this to an attribute into the servlet context.
  2. A servlet filter always opens a Hibernate session. (not a transaction!). It will also (try-finally) close this session.
  3. When a GWT service needs to service a request, Tomcat will create the specified servlet.
  4. Each servlet derives from a BaseServiceImpl abstract servlet.
  5. The BaseServiceImpl overrides "init( ServletConfig config )". Through the "config.getServletContext().getAttribute()"
  6. I am retrieving the injector object, created in the listener.
  7. The injector object calls "injector.injectMembers( this )", which will "instrument" any annotated members in the servlet instance.
  8. When the injector sees a request to inject a field or method parameter, it will look this up in the registry and also attempt to inject any annotations that may exist in the to-be-injected instance.
  9. And so through very simple annotations, it may result in a couple of cascaded injection requests when a servlet gets instantiated.
The very nice thing about Guice is that you no longer have to deal with XML files. It is all programmatic. As soon as you have your "injector" instance, this instance will have been configured with a couple of bindings. Those bindings have matchers on classes and methods and if it finds anything that is annotated, it will perform that instrumentation.

Notice however that Guice is *not* installed on the classloader. This means that just setting "@Inject" on a field for example will not do anything *unless* you retrieve the instance through the injector instance. This latter part is not very easy for
everybody to understand right away, but is the most important aspect (no pun intended) about Guice programming as I have found so far.

Code example? You will need aopalliance.jar and guice-1.0.jar for this to run, downloadable from the Guice website:

ServletContextListener:
================
public class GuiceServletContextListener implements
    ServletContextListener
{
    public GuiceServletContextListener() {
        super();
    }

    public void contextInitialized(ServletContextEvent servletContextEvent)
    {
        ServletContext servletContext =
            servletContextEvent.getServletContext();

        // Create our injector for our application use
        // store it in servlet context.
        Injector injector = Guice.createInjector( new TransactionModel() );
        servletContext.setAttribute( Injector.class.getName(), injector );
    }

    public void contextDestroyed(
        ServletContextEvent servletContextEvent)
    {
    }
}

TransactionModel:
=============
public class TransactionModel implements Module
{
    public void configure(Binder binder)
    {
        binder.bindInterceptor(
            any(), // Match classes.
            annotatedWith(Transactional.class), // Match methods.
            new TransactionInterceptor() // The interceptor.
        );
    }
}

Transactional:
==========
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Transactional {
}

BaseServiceImpl (a base class for any servlet in the application):
==========================================

public abstract class BaseServiceImpl extends RemoteServiceServlet {
    .....
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        Injector injector = (Injector)config.getServletContext().
            getAttribute( Injector.class.getName() );
        injector.injectMembers( this );
    }
    .....
}

CustomerServiceImpl (implementation of GWT service):
====================================
public class CustomerServiceImpl extends BaseServiceImpl implements CustomerService {
    ......
    @Inject
    private CustomerBO customerBO;
    ......
    public CustomerDTO saveCustomer( CustomerDTO dto, boolean isNew )
        throws UIException
    {
        try {
            Customer customer = customerBO.getCustomer( dto.getCustomerId() );
            if ( customer == null ) {
                checkAccess( WebConstants.CUSTOMER_ADD );
                // not found, so create it.
                customer = new Customer();
            } else {
                checkAccess( WebConstants.CUSTOMER_EDIT );
            }

            MapperIF mapper = DozerBeanMapperSingletonWrapper.getInstance();
            mapper.map( custDTO, customer );

            customer = customerBO.saveCustomer( customer, isNew );
            CustomerDTO dto = customerBO.getCustomer( customer.getCustomerId() );

            return dto;
        } catch (ApplicationException ae ) {
            log.error( "Could not save customer", ae );
            throw new UIException( ae.getMessage() );
        }
    }

    ......
}

CustomerBO:
=========

@Singleton
public class CustomerBO extends BaseBO {
    ......
    @Transactional
    public Customer saveCustomer( Customer customer, boolean isNew )
        throws ApplicationException
    {
        Session session = getSession();

        try {
            if ( isNew && customer != null ) {
                throw new ApplicationException(
                    custI18n.getMessage( "error.cust.already.exists" ) );
            }

            // validate will raise an ApplicationException if the customer data is invalid.
            validateCustomer( customer );

            if ( isNew ) {
                session.save( customer );
            } else {
                session.update( customer );
            }

            customer = getCustomer( customer.getCustomerId() );

            return customer;
        } catch (HibernateException he ) {
            log.error( "Could not save customer", he );
            throw new ApplicationException(
                custI18n.getMessage( "error.save.customer" ));
        }
    }
}

==========================

Obviously this code can/should be extended with a variety of things. It should probably check if there is already a transaction ongoing. It should probably add parameters to the transaction interface to find out how the method supports transactions (required, supports, requiresNew, etc) and so on. But for simplicity's
sake, this is the bare minimum.

Notice how, once you have started the injector in the ServiceImpl, the CustomerBO does not need to be declared specifically in the injector. This is some sort of automatic cascading injection effect which happens because the injector is already processing dependent classes. So, luckily, you only need to use the Injector once, which will inject all your other classes where you want them.

Also have a look how to do this for interfaces. What is lacking in the CustomerBO is a separation of persistence with business logic. If you separate this further, you have a start to be able to switch the implementation of your persistence framework.

I am personally contemplating to bring the transaction boundary more forward and wrap this around the methods (where required) of ServiceImpl instead. But I am not sure whether this will work.

Good luck on your own incantations!

Tuesday, January 30, 2007

Project Dune now stable...

Project Dune went stable yesterday. It still needs a detailed customization guide and a user's guide to be really complete, but the main beef is there for people to use and to provide feedback on.

The next steps for this project are aimed at separate modules for SCRUM project management and document management. Naturally, those modules will have certain breakout points as well to allow integration with Project Dune.

The project itself will slow down in new features and aims to resolve issues that the user community will (or should) raise. Then with some more stability under it, we can take it to other levels later on.

Sunday, December 31, 2006

Happy new year!

Happy new year to all. The new year is starting off again with new promises, new resolutions, new business, new projects. I wish everybody well in the coming year and hope that they will get closer to the realization of their dreams.

There are some interesting developments on my own projects. Project Dune has launched a community site: http://pdune.sourceforge.net/ and I am waiting anxiously for people to start using it. The project has been rising in the popularity ranks at SourceForge and it's quite difficult to maintain momentum at these positions.

The good news is that I will be releasing a Beta release pretty soon. There is more working functionality, the main problems have been dealt with and so I am happy to upgrade the status at this time.

It probably won't answer immediately to your needs in your project, because the rules for ownership transfer and updating are rather generic and default. I'll only be able to make some good improvements when I learn more about how people want to use the software.

See you in the next year! I'm off to the beach to celebrate and will be back tomorrow....

G>

Tuesday, December 26, 2006

Measurement

I have read a book titled "Measuring and Managing performance in organizations". It really is an enlightener.

As many know, I am working on a project called "Project Dune" on SourceForge, which is related to quality. You could say that quality is highly dependent on measurement. And for measurement, you need to generate data and do that in such a way that you can historically compare one data-set with another. The end result is hopefully some insight in how you are doing as a team/department/organization.

Well, it is not really that easy. When you start to measure in an organization, you need to generate the data and both activities are coming at a cost of that same organization. Effort removed from normal production work. Well, obviously it is required to find a balance between going for production and generate the data anyway since you need to find a way forward to improve and without information backing up any decisions, you base all decisions on intuition, which in general can be very deceiving.

Project Dune is interesting in that the vision is that it should do the measuring for you. It is basically a similar tool like BugZilla, Mantis and so forth, but in addition to helping with standard administration and tracking, it also helps in day-to-day activities. And that is where the automation is plugged in, next to its envisioned integration points.

When you start to connect a system that knows about user activities, it can connect the data for its users and the larger the domain is where it is connecting "dots", the larger is the area that you can measure across.

The good thing about this is:
  • You get the measurements almost for free, always up-to-date and in real-time
  • You are better supported in day-to-day activities
  • You can spend more effort on your productive tasks without worrying about any process or dependent tasks that you do for others
Of course, it is not really that near to completion, but a BETA is coming out not too far from now. I'm just thinking about server-side call control (security) before I can even call it BETA. So far I have no feedback yet, but hope to see that happening at some time soon.

The statistics for the project are ranking up at the moment. The project is available at the third page in the rankings at this time (103) and seems to be going up still. A new ALPHA-3 release was just issued today. Let's see what happens next :)

Regards,

G>

Friday, December 15, 2006

Progress on Project Dune

I am progressing very quickly recently on the Dune opensource project.

It is a quality automation system. The objective is to make it work similar to BugZilla or Mantis in the sense that it maintains issues, but it also maintains information on:
  • tasks
  • customers
  • projects
  • functional requirement items
  • use cases
  • test cases
  • subversion commits
This way, the project is able to report across the whole area of development eventually. This also opens up the path to automation in traceability and probably therefore control.

I'm thinking of writing a theoretical paper on the subject of quality automation and the information that is supposedly lacking in quality plans, even though data is being "gathered".

check out the Project at Source Forge