diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index ebaf19b..b3ec86f 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Access\CsrfTokenGenerator;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -131,18 +132,16 @@ public function getFormId($form_arg, &$form_state) {
         $form_arg = new $form_arg();
       }
     }
-    // If the $form_arg implements \Drupal\Core\Form\FormInterface, add that as
-    // the callback object and determine the form ID.
-    if (is_object($form_arg) && $form_arg instanceof FormInterface) {
-      $form_state['build_info']['callback_object'] = $form_arg;
-      if ($form_arg instanceof BaseFormIdInterface) {
-        $form_state['build_info']['base_form_id'] = $form_arg->getBaseFormID();
-      }
-      return $form_arg->getFormId();
+    if (!is_object($form_arg) || !($form_arg instanceof FormInterface)) {
+      throw new \Exception(String::format('The form argument @form_arg is not a valid form.', array('@form_arg' => $form_arg)));
     }
 
-    // Otherwise, the $form_arg is the form ID.
-    return $form_arg;
+    // Add the $form_arg as the callback object and determine the form ID.
+    $form_state['build_info']['callback_object'] = $form_arg;
+    if ($form_arg instanceof BaseFormIdInterface) {
+      $form_state['build_info']['base_form_id'] = $form_arg->getBaseFormID();
+    }
+    return $form_arg->getFormId();
   }
 
   /**
@@ -156,8 +155,7 @@ public function getForm($form_arg) {
     unset($args[0]);
     $form_state['build_info']['args'] = array_values($args);
 
-    $form_id = $this->getFormId($form_arg, $form_state);
-    return $this->buildForm($form_id, $form_state);
+    return $this->buildForm($form_arg, $form_state);
   }
 
   /**
@@ -460,15 +458,7 @@ public function retrieveForm($form_id, &$form_state) {
     // the constructor function itself.
     $args = $form_state['build_info']['args'];
 
-    // If an explicit form builder callback is defined we just use it, otherwise
-    // we look for a function named after the $form_id.
-    $callback = $form_id;
-    if (!empty($form_state['build_info']['callback'])) {
-      $callback = $form_state['build_info']['callback'];
-    }
-    elseif (!empty($form_state['build_info']['callback_object'])) {
-      $callback = array($form_state['build_info']['callback_object'], 'buildForm');
-    }
+    $callback = array($form_state['build_info']['callback_object'], 'buildForm');
 
     $form = array();
     // Assign a default CSS class name based on $form_id.
@@ -677,40 +667,8 @@ public function prepareForm($form_id, &$form, &$form_state) {
 
     $form += $this->getElementInfo('form');
     $form += array('#tree' => FALSE, '#parents' => array());
-
-    if (!isset($form['#validate'])) {
-      // Ensure that modules can rely on #validate being set.
-      $form['#validate'] = array();
-      if (isset($form_state['build_info']['callback_object'])) {
-        $form['#validate'][] = array($form_state['build_info']['callback_object'], 'validateForm');
-      }
-      // Check for a handler specific to $form_id.
-      elseif (function_exists($form_id . '_validate')) {
-        $form['#validate'][] = $form_id . '_validate';
-      }
-      // Otherwise check whether this is a shared form and whether there is a
-      // handler for the shared $form_id.
-      elseif (isset($form_state['build_info']['base_form_id']) && function_exists($form_state['build_info']['base_form_id'] . '_validate')) {
-        $form['#validate'][] = $form_state['build_info']['base_form_id'] . '_validate';
-      }
-    }
-
-    if (!isset($form['#submit'])) {
-      // Ensure that modules can rely on #submit being set.
-      $form['#submit'] = array();
-      if (isset($form_state['build_info']['callback_object'])) {
-        $form['#submit'][] = array($form_state['build_info']['callback_object'], 'submitForm');
-      }
-      // Check for a handler specific to $form_id.
-      elseif (function_exists($form_id . '_submit')) {
-        $form['#submit'][] = $form_id . '_submit';
-      }
-      // Otherwise check whether this is a shared form and whether there is a
-      // handler for the shared $form_id.
-      elseif (isset($form_state['build_info']['base_form_id']) && function_exists($form_state['build_info']['base_form_id'] . '_submit')) {
-        $form['#submit'][] = $form_state['build_info']['base_form_id'] . '_submit';
-      }
-    }
+    $form['#validate'][] = array($form_state['build_info']['callback_object'], 'validateForm');
+    $form['#submit'][] = array($form_state['build_info']['callback_object'], 'submitForm');
 
     // If no #theme has been set, automatically apply theme suggestions.
     // theme_form() itself is in #theme_wrappers and not #theme. Therefore, the
diff --git a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
index 8b09681..826fafc 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
@@ -34,6 +34,8 @@ public static function getInfo() {
 
   /**
    * Tests the getFormId() method with a string based form ID.
+   *
+   * @expectedException \Exception
    */
   public function testGetFormIdWithString() {
     $form_arg = 'foo';
@@ -136,8 +138,6 @@ public function testHandleFormStateResponse($class, $form_state_key) {
       }));
 
     $form_state = array();
-    $this->formBuilder->getFormId($form_arg, $form_state);
-
     try {
       $form_state['values'] = array();
       $form_state['input']['form_id'] = $form_id;
@@ -192,8 +192,6 @@ public function testHandleRedirectWithResponse() {
       }));
 
     $form_state = array();
-    $this->formBuilder->getFormId($form_arg, $form_state);
-
     try {
       $form_state['values'] = array();
       $form_state['input']['form_id'] = $form_id;
@@ -205,8 +203,11 @@ public function testHandleRedirectWithResponse() {
     }
     $this->assertSame($response, $form_state['response']);
   }
+
   /**
    * Tests the getForm() method with a string based form ID.
+   *
+   * @expectedException \Exception
    */
   public function testGetFormWithString() {
     $form_id = 'test_form_id';
@@ -248,6 +249,8 @@ public function testGetFormWithClassString() {
 
   /**
    * Tests the buildForm() method with a string based form ID.
+   *
+   * @expectedException \Exception
    */
   public function testBuildFormWithString() {
     $form_id = 'test_form_id';
@@ -333,7 +336,13 @@ public function testGetCache() {
 
     // FormBuilder::buildForm() will be called twice, but the form object will
     // only be called once due to caching.
-    $form_arg = $this->getMockForm($form_id, $expected_form, 1);
+    $form_arg = $this->getMock('Drupal\Core\Form\FormInterface');
+    $form_arg->expects($this->exactly(2))
+      ->method('getFormId')
+      ->will($this->returnValue($form_id));
+    $form_arg->expects($this->once())
+      ->method('buildForm')
+      ->will($this->returnValue($expected_form));
 
     // The CSRF token is checked each time.
     $this->csrfToken->expects($this->exactly(2))
@@ -374,7 +383,7 @@ public function testGetCache() {
     // use the form cache.
     $form_state['input']['form_id'] = $form_id;
     $form_state['input']['form_build_id'] = $form['#build_id'];
-    $this->formBuilder->buildForm($form_id, $form_state);
+    $this->formBuilder->buildForm($form_arg, $form_state);
     $this->assertEmpty($form_state['errors']);
   }
 
@@ -410,6 +419,9 @@ public function testUniqueHtmlId() {
     // Mock a form object that will be built two times.
     $form_arg = $this->getMock('Drupal\Core\Form\FormInterface');
     $form_arg->expects($this->exactly(2))
+      ->method('getFormId')
+      ->will($this->returnValue($form_id));
+    $form_arg->expects($this->exactly(2))
       ->method('buildForm')
       ->will($this->returnValue($expected_form));
 
diff --git a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
index 280e54e..f1fd1db 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
@@ -217,7 +217,7 @@ protected function simulateFormSubmission($form_id, FormInterface $form_arg, arr
     $form_state['input']['op'] = 'Submit';
     $form_state['programmed'] = $programmed;
     $form_state['submitted'] = TRUE;
-    return $this->formBuilder->buildForm($form_id, $form_state);
+    return $this->formBuilder->buildForm($form_arg, $form_state);
   }
 
   /**
